pkcs8_key_parse.c
Go to the documentation of this file.
1 /**
2  * @file pkcs8_key_parse.c
3  * @brief PKCS #8 key parsing
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2026 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.6.4
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/pkcs8_key_parse.h"
37 #include "pkix/x509_key_parse.h"
38 #include "ecc/ec_misc.h"
39 #include "encoding/asn1.h"
40 #include "encoding/oid.h"
41 #include "debug.h"
42 
43 //Check crypto library configuration
44 #if (PEM_SUPPORT == ENABLED)
45 
46 
47 /**
48  * @brief Parse PrivateKeyInfo structure
49  * @param[in] data Pointer to the ASN.1 structure to parse
50  * @param[in] length Length of the ASN.1 structure
51  * @param[out] privateKeyInfo Information resulting from the parsing process
52  * @return Error code
53  **/
54 
56  Pkcs8PrivateKeyInfo *privateKeyInfo)
57 {
58  error_t error;
59  size_t n;
60  size_t oidLen;
61  const uint8_t *oid;
62  Asn1Tag tag;
63 
64  //Clear the PrivateKeyInfo structure
65  osMemset(privateKeyInfo, 0, sizeof(Pkcs8PrivateKeyInfo));
66 
67  //The private key information is encapsulated within a sequence
68  error = asn1ReadSequence(data, length, &tag);
69  //Failed to decode ASN.1 tag?
70  if(error)
71  return error;
72 
73  //Point to the first field of the sequence
74  data = tag.value;
75  length = tag.length;
76 
77  //The Version field identifies the version of OneAsymmetricKey
78  error = asn1ReadInt32(data, length, &tag, &privateKeyInfo->version);
79  //Failed to decode ASN.1 tag?
80  if(error)
81  return error;
82 
83  //Check version
84  if(privateKeyInfo->version != PKCS8_VERSION_1 &&
85  privateKeyInfo->version != PKCS8_VERSION_2)
86  {
87  return ERROR_INVALID_VERSION;
88  }
89 
90  //Point to the next field
91  data += tag.totalLength;
92  length -= tag.totalLength;
93 
94  //Read PrivateKeyAlgorithm field
95  error = pkcs8ParsePrivateKeyAlgo(data, length, &n, privateKeyInfo);
96  //Failed to decode ASN.1 tag?
97  if(error)
98  return error;
99 
100  //Point to the next field
101  data += n;
102  length -= n;
103 
104  //The PrivateKey is encapsulated within an octet string
105  error = asn1ReadOctetString(data, length, &tag);
106  //Failed to decode ASN.1 tag?
107  if(error)
108  return error;
109 
110  //Get the private key algorithm identifier
111  oid = privateKeyInfo->oid.value;
112  oidLen = privateKeyInfo->oid.length;
113 
114 #if (RSA_SUPPORT == ENABLED)
115  //RSA or RSA-PSS algorithm identifier?
116  if(OID_COMP(oid, oidLen, RSA_ENCRYPTION_OID) == 0 ||
118  {
119  //Read RSAPrivateKey structure
120  error = pkcs8ParseRsaPrivateKey(tag.value, tag.length,
121  &privateKeyInfo->rsaPrivateKey);
122  }
123  else
124 #endif
125 #if (DSA_SUPPORT == ENABLED)
126  //DSA algorithm identifier?
127  if(OID_COMP(oid, oidLen, DSA_OID) == 0)
128  {
129  //Read DSAPrivateKey structure
130  error = pkcs8ParseDsaPrivateKey(tag.value, tag.length, NULL,
131  &privateKeyInfo->dsaPrivateKey, NULL);
132  }
133  else
134 #endif
135 #if (EC_SUPPORT == ENABLED)
136  //EC public key identifier?
138  {
139  //Read ECPrivateKey structure
140  error = pkcs8ParseEcPrivateKey(tag.value, tag.length,
141  &privateKeyInfo->ecParams, &privateKeyInfo->ecPrivateKey,
142  &privateKeyInfo->ecPublicKey);
143  }
144  else
145 #endif
146 #if (ED25519_SUPPORT == ENABLED)
147  //X25519 or Ed25519 algorithm identifier?
148  if(OID_COMP(oid, oidLen, X25519_OID) == 0 ||
149  OID_COMP(oid, oidLen, ED25519_OID) == 0)
150  {
151  //Read CurvePrivateKey structure
152  error = pkcs8ParseEddsaPrivateKey(tag.value, tag.length,
153  &privateKeyInfo->eddsaPrivateKey);
154  }
155  else
156 #endif
157 #if (ED448_SUPPORT == ENABLED)
158  //X448 or Ed448 algorithm identifier?
159  if(OID_COMP(oid, oidLen, X448_OID) == 0 ||
160  OID_COMP(oid, oidLen, ED448_OID) == 0)
161  {
162  //Read CurvePrivateKey structure
163  error = pkcs8ParseEddsaPrivateKey(tag.value, tag.length,
164  &privateKeyInfo->eddsaPrivateKey);
165  }
166  else
167 #endif
168 #if (MLDSA44_SUPPORT == ENABLED)
169  //ML-DSA-44 algorithm identifier?
170  if(OID_COMP(oid, oidLen, MLDSA44_OID) == 0)
171  {
172  //Read ML-DSA-44-PrivateKey structure
173  error = pkcs8ParseMldsaPrivateKey(tag.value, tag.length,
174  &privateKeyInfo->mldsaPrivateKey);
175  }
176  else
177 #endif
178 #if (MLDSA65_SUPPORT == ENABLED)
179  //ML-DSA-65 algorithm identifier?
180  if(OID_COMP(oid, oidLen, MLDSA65_OID) == 0)
181  {
182  //Read ML-DSA-65-PrivateKey structure
183  error = pkcs8ParseMldsaPrivateKey(tag.value, tag.length,
184  &privateKeyInfo->mldsaPrivateKey);
185  }
186  else
187 #endif
188 #if (MLDSA87_SUPPORT == ENABLED)
189  //ML-DSA-87 algorithm identifier?
190  if(OID_COMP(oid, oidLen, MLDSA87_OID) == 0)
191  {
192  //Read ML-DSA-87-PrivateKey structure
193  error = pkcs8ParseMldsaPrivateKey(tag.value, tag.length,
194  &privateKeyInfo->mldsaPrivateKey);
195  }
196  else
197 #endif
198  //Unknown algorithm identifier?
199  {
200  //Report an error
201  error = ERROR_WRONG_IDENTIFIER;
202  }
203 
204  //Any error to report?
205  if(error)
206  return error;
207 
208  //Point to the next field
209  data += tag.totalLength;
210  length -= tag.totalLength;
211 
212  //Check version
213  if(privateKeyInfo->version == PKCS8_VERSION_2)
214  {
215  //The OneAsymmetricKey structure allows for the public key and additional
216  //attributes about the key to be included as well (refer to RFC 8410,
217  //section 7)
218  while(length > 0)
219  {
220  //Read current attribute
221  error = asn1ReadTag(data, length, &tag);
222  //Failed to decode ASN.1 tag?
223  if(error)
224  return error;
225 
226  //Explicit tagging shall be used to encode each optional attribute
228  return ERROR_INVALID_CLASS;
229 
230  //Check attribute type
231  if(tag.objType == 1)
232  {
233 #if (ED25519_SUPPORT == ENABLED)
234  //X25519 or Ed25519 algorithm identifier?
235  if(OID_COMP(oid, oidLen, X25519_OID) == 0 ||
236  OID_COMP(oid, oidLen, ED25519_OID) == 0)
237  {
238  //The publicKey field contains the elliptic curve public key
239  //associated with the private key in question
240  error = pkcs8ParseEddsaPublicKey(tag.value, tag.length,
241  &privateKeyInfo->eddsaPublicKey);
242  //Any error to report?
243  if(error)
244  return error;
245  }
246  else
247 #endif
248 #if (ED448_SUPPORT == ENABLED)
249  //X448 or Ed448 algorithm identifier?
250  if(OID_COMP(oid, oidLen, X448_OID) == 0 ||
251  OID_COMP(oid, oidLen, ED448_OID) == 0)
252  {
253  //The publicKey field contains the elliptic curve public key
254  //associated with the private key in question
255  error = pkcs8ParseEddsaPublicKey(tag.value, tag.length,
256  &privateKeyInfo->eddsaPublicKey);
257  //Any error to report?
258  if(error)
259  return error;
260  }
261  else
262 #endif
263  //Unknown algorithm identifier?
264  {
265  //Just for sanity
266  }
267  }
268 
269  //Next attribute
270  data += tag.totalLength;
271  length -= tag.totalLength;
272  }
273  }
274 
275  //Successful processing
276  return NO_ERROR;
277 }
278 
279 
280 /**
281  * @brief Parse PrivateKeyAlgorithm structure
282  * @param[in] data Pointer to the ASN.1 structure to parse
283  * @param[in] length Length of the ASN.1 structure
284  * @param[out] totalLength Number of bytes that have been parsed
285  * @param[out] privateKeyInfo Information resulting from the parsing process
286  * @return Error code
287  **/
288 
290  size_t *totalLength, Pkcs8PrivateKeyInfo *privateKeyInfo)
291 {
292  error_t error;
293  Asn1Tag tag;
294 
295  //Read the contents of the PrivateKeyAlgorithm structure
296  error = asn1ReadSequence(data, length, &tag);
297  //Failed to decode ASN.1 tag?
298  if(error)
299  return error;
300 
301  //Save the total length of the sequence
302  *totalLength = tag.totalLength;
303 
304  //Point to the first field of the sequence
305  data = tag.value;
306  length = tag.length;
307 
308  //Read the private key algorithm identifier
309  error = asn1ReadOid(data, length, &tag);
310  //Failed to decode ASN.1 tag?
311  if(error)
312  return error;
313 
314  //Save the private key algorithm identifier
315  privateKeyInfo->oid.value = tag.value;
316  privateKeyInfo->oid.length = tag.length;
317 
318  //Point to the next field (if any)
319  data += tag.totalLength;
320  length -= tag.totalLength;
321 
322 #if (RSA_SUPPORT == ENABLED)
323  //RSA algorithm identifier?
325  {
326  //The parameters field must have ASN.1 type NULL for this algorithm
327  //identifier (refer to RFC 3279, section 2.3.1)
328  error = NO_ERROR;
329  }
330  //RSA-PSS algorithm identifier?
331  else if(!asn1CheckOid(&tag, RSASSA_PSS_OID, sizeof(RSASSA_PSS_OID)))
332  {
333  //The parameters may be either absent or present when used as subject
334  //public key information (refer to RFC 4055, section 3.1)
335  error = NO_ERROR;
336  }
337  else
338 #endif
339 #if (DSA_SUPPORT == ENABLED)
340  //DSA algorithm identifier?
341  if(!asn1CheckOid(&tag, DSA_OID, sizeof(DSA_OID)))
342  {
343  //Read DsaParameters structure
344  error = x509ParseDsaParameters(data, length, &privateKeyInfo->dsaParams);
345  }
346  else
347 #endif
348 #if (EC_SUPPORT == ENABLED)
349  //EC public key identifier?
351  {
352  //Read ECParameters structure
353  error = x509ParseEcParameters(data, length, &privateKeyInfo->ecParams);
354  }
355  else
356 #endif
357 #if (ED25519_SUPPORT == ENABLED)
358  //X25519 or Ed25519 algorithm identifier?
359  if(!asn1CheckOid(&tag, X25519_OID, sizeof(X25519_OID)) ||
360  !asn1CheckOid(&tag, ED25519_OID, sizeof(ED25519_OID)))
361  {
362  //For all of the OIDs, the parameters must be absent (refer to RFC 8410,
363  //section 3)
364  error = NO_ERROR;
365  }
366  else
367 #endif
368 #if (ED448_SUPPORT == ENABLED)
369  //X448 or Ed448 algorithm identifier?
370  if(!asn1CheckOid(&tag, X448_OID, sizeof(X448_OID)) ||
371  !asn1CheckOid(&tag, ED448_OID, sizeof(ED448_OID)))
372  {
373  //For all of the OIDs, the parameters must be absent (refer to RFC 8410,
374  //section 3)
375  error = NO_ERROR;
376  }
377  else
378 #endif
379 #if (MLDSA44_SUPPORT == ENABLED)
380  //ML-DSA-44 algorithm identifier?
381  if(!asn1CheckOid(&tag, MLDSA44_OID, sizeof(MLDSA44_OID)))
382  {
383  //The contents of the parameters component must be absent (refer to
384  //RFC 9881, section 2)
385  error = NO_ERROR;
386  }
387  else
388 #endif
389 #if (MLDSA65_SUPPORT == ENABLED)
390  //ML-DSA-65 algorithm identifier?
391  if(!asn1CheckOid(&tag, MLDSA65_OID, sizeof(MLDSA65_OID)))
392  {
393  //The contents of the parameters component must be absent (refer to
394  //RFC 9881, section 2)
395  error = NO_ERROR;
396  }
397  else
398 #endif
399 #if (MLDSA87_SUPPORT == ENABLED)
400  //ML-DSA-87 algorithm identifier?
401  if(!asn1CheckOid(&tag, MLDSA87_OID, sizeof(MLDSA87_OID)))
402  {
403  //The contents of the parameters component must be absent (refer to
404  //RFC 9881, section 2)
405  error = NO_ERROR;
406  }
407  else
408 #endif
409  //Unknown algorithm identifier?
410  {
411  //Report an error
412  error = ERROR_WRONG_IDENTIFIER;
413  }
414 
415  //Return status code
416  return error;
417 }
418 
419 
420 /**
421  * @brief Parse RSAPrivateKey structure
422  * @param[in] data Pointer to the ASN.1 structure to parse
423  * @param[in] length Length of the ASN.1 structure
424  * @param[out] rsaPrivateKey Information resulting from the parsing process
425  * @return Error code
426  **/
427 
429  Pkcs8RsaPrivateKey *rsaPrivateKey)
430 {
431  error_t error;
432  Asn1Tag tag;
433 
434  //Read RSAPrivateKey structure
435  error = asn1ReadSequence(data, length, &tag);
436  //Failed to decode ASN.1 tag?
437  if(error)
438  return error;
439 
440  //Point to the first field
441  data = tag.value;
442  length = tag.length;
443 
444  //Read Version field
445  error = asn1ReadInt32(data, length, &tag, &rsaPrivateKey->version);
446  //Failed to decode ASN.1 tag?
447  if(error)
448  return error;
449 
450  //Point to the next field
451  data += tag.totalLength;
452  length -= tag.totalLength;
453 
454  //Read Modulus field
455  error = asn1ReadTag(data, length, &tag);
456  //Failed to decode ASN.1 tag?
457  if(error)
458  return error;
459 
460  //Enforce encoding, class and type
462  //Invalid tag?
463  if(error)
464  return error;
465 
466  //Save the modulus
467  rsaPrivateKey->n.value = tag.value;
468  rsaPrivateKey->n.length = tag.length;
469 
470  //Point to the next field
471  data += tag.totalLength;
472  length -= tag.totalLength;
473 
474  //Read PublicExponent field
475  error = asn1ReadTag(data, length, &tag);
476  //Failed to decode ASN.1 tag?
477  if(error)
478  return error;
479 
480  //Enforce encoding, class and type
482  //Invalid tag?
483  if(error)
484  return error;
485 
486  //Save the public exponent
487  rsaPrivateKey->e.value = tag.value;
488  rsaPrivateKey->e.length = tag.length;
489 
490  //Point to the next field
491  data += tag.totalLength;
492  length -= tag.totalLength;
493 
494  //Read PrivateExponent field
495  error = asn1ReadTag(data, length, &tag);
496  //Failed to decode ASN.1 tag?
497  if(error)
498  return error;
499 
500  //Enforce encoding, class and type
502  //Invalid tag?
503  if(error)
504  return error;
505 
506  //Save the private exponent
507  rsaPrivateKey->d.value = tag.value;
508  rsaPrivateKey->d.length = tag.length;
509 
510  //Point to the next field
511  data += tag.totalLength;
512  length -= tag.totalLength;
513 
514  //Read Prime1 field
515  error = asn1ReadTag(data, length, &tag);
516  //Failed to decode ASN.1 tag?
517  if(error)
518  return error;
519 
520  //Enforce encoding, class and type
522  //Invalid tag?
523  if(error)
524  return error;
525 
526  //Save the first factor
527  rsaPrivateKey->p.value = tag.value;
528  rsaPrivateKey->p.length = tag.length;
529 
530  //Point to the next field
531  data += tag.totalLength;
532  length -= tag.totalLength;
533 
534  //Read Prime2 field
535  error = asn1ReadTag(data, length, &tag);
536  //Failed to decode ASN.1 tag?
537  if(error)
538  return error;
539 
540  //Enforce encoding, class and type
542  //Invalid tag?
543  if(error)
544  return error;
545 
546  //Save the second factor
547  rsaPrivateKey->q.value = tag.value;
548  rsaPrivateKey->q.length = tag.length;
549 
550  //Point to the next field
551  data += tag.totalLength;
552  length -= tag.totalLength;
553 
554  //Read Exponent1 field
555  error = asn1ReadTag(data, length, &tag);
556  //Failed to decode ASN.1 tag?
557  if(error)
558  return error;
559 
560  //Enforce encoding, class and type
562  //Invalid tag?
563  if(error)
564  return error;
565 
566  //Save the first exponent
567  rsaPrivateKey->dp.value = tag.value;
568  rsaPrivateKey->dp.length = tag.length;
569 
570  //Point to the next field
571  data += tag.totalLength;
572  length -= tag.totalLength;
573 
574  //Read Exponent2 field
575  error = asn1ReadTag(data, length, &tag);
576  //Failed to decode ASN.1 tag?
577  if(error)
578  return error;
579 
580  //Enforce encoding, class and type
582  //Invalid tag?
583  if(error)
584  return error;
585 
586  //Save the second exponent
587  rsaPrivateKey->dq.value = tag.value;
588  rsaPrivateKey->dq.length = tag.length;
589 
590  //Point to the next field
591  data += tag.totalLength;
592  length -= tag.totalLength;
593 
594  //Read Coefficient field
595  error = asn1ReadTag(data, length, &tag);
596  //Failed to decode ASN.1 tag?
597  if(error)
598  return error;
599 
600  //Enforce encoding, class and type
602  //Invalid tag?
603  if(error)
604  return error;
605 
606  //Save the coefficient
607  rsaPrivateKey->qinv.value = tag.value;
608  rsaPrivateKey->qinv.length = tag.length;
609 
610  //Successful processing
611  return NO_ERROR;
612 }
613 
614 
615 /**
616  * @brief Parse DSAPrivateKey structure
617  * @param[in] data Pointer to the ASN.1 structure to parse
618  * @param[in] length Length of the ASN.1 structure
619  * @param[out] dsaParams DSA domain parameters
620  * @param[out] dsaPrivateKey DSA private key
621  * @param[out] dsaPublicKey DSA public key
622  * @return Error code
623  **/
624 
626  X509DsaParameters *dsaParams, Pkcs8DsaPrivateKey *dsaPrivateKey,
627  X509DsaPublicKey *dsaPublicKey)
628 {
629  error_t error;
630  int32_t version;
631  Asn1Tag tag;
632 
633  //The DSA domain parameters can be optionally parsed
634  if(dsaParams != NULL && dsaPublicKey != NULL)
635  {
636  //Read DSAPrivateKey structure
637  error = asn1ReadSequence(data, length, &tag);
638  //Failed to decode ASN.1 tag?
639  if(error)
640  return error;
641 
642  //Point to the first field of the sequence
643  data = tag.value;
644  length = tag.length;
645 
646  //Read version
647  error = asn1ReadInt32(data, length, &tag, &version);
648  //Failed to decode ASN.1 tag?
649  if(error)
650  return error;
651 
652  //Point to the next field
653  data += tag.totalLength;
654  length -= tag.totalLength;
655 
656  //Read the parameter p
657  error = asn1ReadTag(data, length, &tag);
658  //Failed to decode ASN.1 tag?
659  if(error)
660  return error;
661 
662  //Enforce encoding, class and type
663  error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL,
665  //Invalid tag?
666  if(error)
667  return error;
668 
669  //Save the parameter p
670  dsaParams->p.value = tag.value;
671  dsaParams->p.length = tag.length;
672 
673  //Point to the next field
674  data += tag.totalLength;
675  length -= tag.totalLength;
676 
677  //Read the parameter q
678  error = asn1ReadTag(data, length, &tag);
679  //Failed to decode ASN.1 tag?
680  if(error)
681  return error;
682 
683  //Enforce encoding, class and type
684  error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL,
686  //Invalid tag?
687  if(error)
688  return error;
689 
690  //Save the parameter q
691  dsaParams->q.value = tag.value;
692  dsaParams->q.length = tag.length;
693 
694  //Point to the next field
695  data += tag.totalLength;
696  length -= tag.totalLength;
697 
698  //Read the parameter g
699  error = asn1ReadTag(data, length, &tag);
700  //Failed to decode ASN.1 tag?
701  if(error)
702  return error;
703 
704  //Enforce encoding, class and type
705  error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL,
707  //Invalid tag?
708  if(error)
709  return error;
710 
711  //Save the parameter g
712  dsaParams->g.value = tag.value;
713  dsaParams->g.length = tag.length;
714 
715  //Point to the next field
716  data += tag.totalLength;
717  length -= tag.totalLength;
718 
719  //Read the public value y
720  error = asn1ReadTag(data, length, &tag);
721  //Failed to decode ASN.1 tag?
722  if(error)
723  return error;
724 
725  //Enforce encoding, class and type
726  error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL,
728  //Invalid tag?
729  if(error)
730  return error;
731 
732  //Save the public value y
733  dsaPublicKey->y.value = tag.value;
734  dsaPublicKey->y.length = tag.length;
735 
736  //Point to the next field
737  data += tag.totalLength;
738  length -= tag.totalLength;
739  }
740 
741  //Read the private value x
742  error = asn1ReadTag(data, length, &tag);
743  //Failed to decode ASN.1 tag?
744  if(error)
745  return error;
746 
747  //Enforce encoding, class and type
749  //Invalid tag?
750  if(error)
751  return error;
752 
753  //Save the private value x
754  dsaPrivateKey->x.value = tag.value;
755  dsaPrivateKey->x.length = tag.length;
756 
757  //Successful processing
758  return NO_ERROR;
759 }
760 
761 
762 /**
763  * @brief Parse ECPrivateKey structure
764  * @param[in] data Pointer to the ASN.1 structure to parse
765  * @param[in] length Length of the ASN.1 structure
766  * @param[out] ecParams EC domain parameters
767  * @param[out] ecPrivateKey EC private key
768  * @param[out] ecPublicKey EC public key
769  * @return Error code
770  **/
771 
772 error_t pkcs8ParseEcPrivateKey(const uint8_t *data, size_t length,
773  X509EcParameters *ecParams, Pkcs8EcPrivateKey *ecPrivateKey,
774  X509EcPublicKey *ecPublicKey)
775 {
776  error_t error;
777  Asn1Tag tag;
778 
779  //Read ECPrivateKey structure
780  error = asn1ReadSequence(data, length, &tag);
781  //Failed to decode ASN.1 tag?
782  if(error)
783  return error;
784 
785  //Point to the first field
786  data = tag.value;
787  length = tag.length;
788 
789  //Read Version field
790  error = asn1ReadInt32(data, length, &tag, &ecPrivateKey->version);
791  //Failed to decode ASN.1 tag?
792  if(error)
793  return error;
794 
795  //Point to the next field
796  data += tag.totalLength;
797  length -= tag.totalLength;
798 
799  //Read PrivateKey field
800  error = asn1ReadOctetString(data, length, &tag);
801  //Failed to decode ASN.1 tag?
802  if(error)
803  return error;
804 
805  //Save the EC private key
806  ecPrivateKey->d.value = tag.value;
807  ecPrivateKey->d.length = tag.length;
808 
809  //Point to the next field
810  data += tag.totalLength;
811  length -= tag.totalLength;
812 
813  //Loop through optional attributes
814  while(length > 0)
815  {
816  //Read current attribute
817  error = asn1ReadTag(data, length, &tag);
818  //Failed to decode ASN.1 tag?
819  if(error)
820  return error;
821 
822  //Explicit tagging shall be used to encode each optional attribute
824  return ERROR_INVALID_CLASS;
825 
826  //Check attribute type
827  if(tag.objType == 0)
828  {
829  //The parameters field specifies the elliptic curve domain parameters
830  //associated to the private key
831  error = x509ParseEcParameters(tag.value, tag.length, ecParams);
832  //Any error to report?
833  if(error)
834  return error;
835  }
836  else if(tag.objType == 1)
837  {
838  //The publicKey field contains the elliptic curve public key associated
839  //with the private key in question
840  error = pkcs8ParseEcPublicKey(tag.value, tag.length, ecPublicKey);
841  //Any error to report?
842  if(error)
843  return error;
844  }
845  else
846  {
847  //Ignore unknown attribute
848  }
849 
850  //Next attribute
851  data += tag.totalLength;
852  length -= tag.totalLength;
853  }
854 
855  //Successful processing
856  return NO_ERROR;
857 }
858 
859 
860 /**
861  * @brief Parse publicKey structure
862  * @param[in] data Pointer to the ASN.1 structure to parse
863  * @param[in] length Length of the ASN.1 structure
864  * @param[out] ecPublicKey EC public key
865  * @return Error code
866  **/
867 
868 error_t pkcs8ParseEcPublicKey(const uint8_t *data, size_t length,
869  X509EcPublicKey *ecPublicKey)
870 {
871  error_t error;
872  Asn1Tag tag;
873 
874  //The public key is encapsulated within a bit string
875  error = asn1ReadTag(data, length, &tag);
876  //Failed to decode ASN.1 tag?
877  if(error)
878  return error;
879 
880  //Enforce encoding, class and type
881  error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL,
883  //Failed to decode ASN.1 tag?
884  if(error)
885  return error;
886 
887  //The bit string shall contain an initial octet which encodes the number
888  //of unused bits in the final subsequent octet
889  if(tag.length < 1 || tag.value[0] != 0)
890  return ERROR_INVALID_SYNTAX;
891 
892  //Save the EC public key
893  ecPublicKey->q.value = tag.value + 1;
894  ecPublicKey->q.length = tag.length - 1;
895 
896  //Successful processing
897  return NO_ERROR;
898 }
899 
900 
901 /**
902  * @brief Parse CurvePrivateKey structure
903  * @param[in] data Pointer to the ASN.1 structure to parse
904  * @param[in] length Length of the ASN.1 structure
905  * @param[out] eddsaPrivateKey EdDSA private key
906  * @return Error code
907  **/
908 
910  Pkcs8EddsaPrivateKey *eddsaPrivateKey)
911 {
912  error_t error;
913  Asn1Tag tag;
914 
915  //The CurvePrivateKey structure is encapsulated within an octet string
916  error = asn1ReadOctetString(data, length, &tag);
917  //Failed to decode ASN.1 tag?
918  if(error)
919  return error;
920 
921  //Save the EdDSA private key
922  eddsaPrivateKey->d.value = tag.value;
923  eddsaPrivateKey->d.length = tag.length;
924 
925  //Successful processing
926  return NO_ERROR;
927 }
928 
929 
930 /**
931  * @brief Parse publicKey structure
932  * @param[in] data Pointer to the ASN.1 structure to parse
933  * @param[in] length Length of the ASN.1 structure
934  * @param[out] eddsaPublicKey EdDSA public key
935  * @return Error code
936  **/
937 
939  Pkcs8EddsaPublicKey *eddsaPublicKey)
940 {
941  //The bit string shall contain an initial octet which encodes the number
942  //of unused bits in the final subsequent octet
943  if(length < 1 || data[0] != 0)
944  return ERROR_INVALID_SYNTAX;
945 
946  //Save the EdDSA public key
947  eddsaPublicKey->q.value = data + 1;
948  eddsaPublicKey->q.length = length - 1;
949 
950  //Successful processing
951  return NO_ERROR;
952 }
953 
954 
955 /**
956  * @brief Parse ML-DSA-PrivateKey structure
957  * @param[in] data Pointer to the ASN.1 structure to parse
958  * @param[in] length Length of the ASN.1 structure
959  * @param[out] mldsaPrivateKey ML-DSA private key
960  * @return Error code
961  **/
962 
964  Pkcs8MldsaPrivateKey *mldsaPrivateKey)
965 {
966  error_t error;
967  Asn1Tag tag;
968 
969  //For ML-DSA private keys, the privateKey field in OneAsymmetricKey contains
970  //a CHOICE structure (refer to RFC 9881, section 6)
971  error = asn1ReadTag(data, length, &tag);
972  //Failed to decode ASN.1 tag?
973  if(error)
974  return error;
975 
976  //The CHOICE allows three representations of the private key
978  tag.objType == 0)
979  {
980  //The seed format contains just the 32-byte seed value from which both
981  //the expanded private key and public key can be derived
982  mldsaPrivateKey->seed.value = tag.value;
983  mldsaPrivateKey->seed.length = tag.length;
984  }
985  else if(!tag.constructed && tag.objClass == ASN1_CLASS_UNIVERSAL &&
987  {
988  //The expandedKey format contains the expanded private key that was
989  //derived from the seed
990  mldsaPrivateKey->expandedKey.value = tag.value;
991  mldsaPrivateKey->expandedKey.length = tag.length;
992  }
993  else if(tag.constructed && tag.objClass == ASN1_CLASS_UNIVERSAL &&
995  {
996  //The both format contains both the seed and expanded private key
997  data = tag.value;
998  length = tag.length;
999 
1000  //Read seed field
1001  error = asn1ReadOctetString(data, length, &tag);
1002  //Failed to decode ASN.1 tag?
1003  if(error)
1004  return error;
1005 
1006  //Save the seed
1007  mldsaPrivateKey->seed.value = tag.value;
1008  mldsaPrivateKey->seed.length = tag.length;
1009 
1010  //Point to the next field
1011  data += tag.totalLength;
1012  length -= tag.totalLength;
1013 
1014  //Read expandedKey field
1015  error = asn1ReadOctetString(data, length, &tag);
1016  //Failed to decode ASN.1 tag?
1017  if(error)
1018  return error;
1019 
1020  //Save the expanded private key
1021  mldsaPrivateKey->expandedKey.value = tag.value;
1022  mldsaPrivateKey->expandedKey.length = tag.length;
1023  }
1024  else
1025  {
1026  //Malformed structure
1027  return ERROR_WRONG_ENCODING;
1028  }
1029 
1030  //Successful processing
1031  return NO_ERROR;
1032 }
1033 
1034 
1035 /**
1036  * @brief Parse EncryptedPrivateKeyInfo structure
1037  * @param[in] data Pointer to the ASN.1 structure to parse
1038  * @param[in] length Length of the ASN.1 structure
1039  * @param[out] encryptedPrivateKeyInfo Information resulting from the parsing process
1040  * @return Error code
1041  **/
1042 
1044  Pkcs8EncryptedPrivateKeyInfo *encryptedPrivateKeyInfo)
1045 {
1046  error_t error;
1047  size_t n;
1048  Asn1Tag tag;
1049 
1050  //Read EncryptedPrivateKeyInfo structure
1051  error = asn1ReadSequence(data, length, &tag);
1052  //Failed to decode ASN.1 tag?
1053  if(error)
1054  return error;
1055 
1056  //Point to the first field
1057  data = tag.value;
1058  length = tag.length;
1059 
1060  //Parse EncryptionAlgorithmIdentifier structure
1062  &encryptedPrivateKeyInfo->encryptionAlgo);
1063  //Any error to report?
1064  if(error)
1065  return error;
1066 
1067  //Point to the next field
1068  data += n;
1069  length -= n;
1070 
1071  //The EncryptedData is encapsulated within an octet string
1072  error = asn1ReadOctetString(data, length, &tag);
1073  //Failed to decode ASN.1 tag?
1074  if(error)
1075  return error;
1076 
1077  //The EncryptedData is the result of encrypting the private-key information
1078  encryptedPrivateKeyInfo->encryptedData.value = tag.value;
1079  encryptedPrivateKeyInfo->encryptedData.length = tag.length;
1080 
1081  //Successful processing
1082  return NO_ERROR;
1083 }
1084 
1085 
1086 /**
1087  * @brief Parse EncryptionAlgorithmIdentifier structure
1088  * @param[in] data Pointer to the ASN.1 structure to parse
1089  * @param[in] length Length of the ASN.1 structure
1090  * @param[out] totalLength Number of bytes that have been parsed
1091  * @param[out] encryptionAlgoId Information resulting from the parsing process
1092  * @return Error code
1093  **/
1094 
1096  size_t *totalLength, X509AlgoId *encryptionAlgoId)
1097 {
1098  error_t error;
1099  Asn1Tag tag;
1100 
1101  //Read the contents of the EncryptionAlgorithmIdentifier structure
1102  error = asn1ReadSequence(data, length, &tag);
1103  //Failed to decode ASN.1 tag?
1104  if(error)
1105  return error;
1106 
1107  //Save the total length of the sequence
1108  *totalLength = tag.totalLength;
1109 
1110  //Point to the first field of the sequence
1111  data = tag.value;
1112  length = tag.length;
1113 
1114  //Read the encryption algorithm identifier
1115  error = asn1ReadOid(data, length, &tag);
1116  //Failed to decode ASN.1 tag?
1117  if(error)
1118  return error;
1119 
1120  //Save the encryption algorithm identifier
1121  encryptionAlgoId->oid.value = tag.value;
1122  encryptionAlgoId->oid.length = tag.length;
1123 
1124  //Point to the next field (if any)
1125  data += tag.totalLength;
1126  length -= tag.totalLength;
1127 
1128  //The contents of the optional parameters field will vary according to the
1129  //algorithm identified
1130  encryptionAlgoId->params.value = data;
1131  encryptionAlgoId->params.length = length;
1132 
1133  //Return status code
1134  return error;
1135 }
1136 
1137 
1138 /**
1139  * @brief Import an RSA private key
1140  * @param[out] privateKey RSA private key
1141  * @param[in] privateKeyInfo Private key information
1142  * @return Error code
1143  **/
1144 
1146  const Pkcs8PrivateKeyInfo *privateKeyInfo)
1147 {
1148  error_t error;
1149 
1150 #if (RSA_SUPPORT == ENABLED)
1151  const uint8_t *oid;
1152  size_t oidLen;
1153 
1154  //Get the private key algorithm identifier
1155  oid = privateKeyInfo->oid.value;
1156  oidLen = privateKeyInfo->oid.length;
1157 
1158  //RSA or RSA-PSS algorithm identifier?
1159  if(OID_COMP(oid, oidLen, RSA_ENCRYPTION_OID) == 0 ||
1161  {
1162  //Sanity check
1163  if(privateKeyInfo->rsaPrivateKey.n.value != NULL &&
1164  privateKeyInfo->rsaPrivateKey.e.value != NULL &&
1165  privateKeyInfo->rsaPrivateKey.d.value != NULL &&
1166  privateKeyInfo->rsaPrivateKey.p.value != NULL &&
1167  privateKeyInfo->rsaPrivateKey.q.value != NULL &&
1168  privateKeyInfo->rsaPrivateKey.dp.value != NULL &&
1169  privateKeyInfo->rsaPrivateKey.dq.value != NULL &&
1170  privateKeyInfo->rsaPrivateKey.qinv.value != NULL)
1171  {
1172  //Read modulus
1173  error = mpiImport(&privateKey->n,
1174  privateKeyInfo->rsaPrivateKey.n.value,
1175  privateKeyInfo->rsaPrivateKey.n.length, MPI_FORMAT_BIG_ENDIAN);
1176 
1177  //Check status code
1178  if(!error)
1179  {
1180  //Read public exponent
1181  error = mpiImport(&privateKey->e,
1182  privateKeyInfo->rsaPrivateKey.e.value,
1183  privateKeyInfo->rsaPrivateKey.e.length, MPI_FORMAT_BIG_ENDIAN);
1184  }
1185 
1186  //Check status code
1187  if(!error)
1188  {
1189  //Read private exponent
1190  error = mpiImport(&privateKey->d,
1191  privateKeyInfo->rsaPrivateKey.d.value,
1192  privateKeyInfo->rsaPrivateKey.d.length, MPI_FORMAT_BIG_ENDIAN);
1193  }
1194 
1195  //Check status code
1196  if(!error)
1197  {
1198  //Read first factor
1199  error = mpiImport(&privateKey->p,
1200  privateKeyInfo->rsaPrivateKey.p.value,
1201  privateKeyInfo->rsaPrivateKey.p.length, MPI_FORMAT_BIG_ENDIAN);
1202  }
1203 
1204  //Check status code
1205  if(!error)
1206  {
1207  //Read second factor
1208  error = mpiImport(&privateKey->q,
1209  privateKeyInfo->rsaPrivateKey.q.value,
1210  privateKeyInfo->rsaPrivateKey.q.length, MPI_FORMAT_BIG_ENDIAN);
1211  }
1212 
1213  //Check status code
1214  if(!error)
1215  {
1216  //Read first exponent
1217  error = mpiImport(&privateKey->dp,
1218  privateKeyInfo->rsaPrivateKey.dp.value,
1219  privateKeyInfo->rsaPrivateKey.dp.length, MPI_FORMAT_BIG_ENDIAN);
1220  }
1221 
1222  //Check status code
1223  if(!error)
1224  {
1225  //Read second exponent
1226  error = mpiImport(&privateKey->dq,
1227  privateKeyInfo->rsaPrivateKey.dq.value,
1228  privateKeyInfo->rsaPrivateKey.dq.length, MPI_FORMAT_BIG_ENDIAN);
1229  }
1230 
1231  //Check status code
1232  if(!error)
1233  {
1234  //Read coefficient
1235  error = mpiImport(&privateKey->qinv,
1236  privateKeyInfo->rsaPrivateKey.qinv.value,
1237  privateKeyInfo->rsaPrivateKey.qinv.length, MPI_FORMAT_BIG_ENDIAN);
1238  }
1239 
1240  //Check status code
1241  if(!error)
1242  {
1243  //Dump RSA private key
1244  TRACE_DEBUG("RSA private key:\r\n");
1245  TRACE_DEBUG(" Modulus:\r\n");
1246  TRACE_DEBUG_MPI(" ", &privateKey->n);
1247  TRACE_DEBUG(" Public exponent:\r\n");
1248  TRACE_DEBUG_MPI(" ", &privateKey->e);
1249  TRACE_DEBUG(" Private exponent:\r\n");
1250  TRACE_DEBUG_MPI(" ", &privateKey->d);
1251  TRACE_DEBUG(" Prime 1:\r\n");
1252  TRACE_DEBUG_MPI(" ", &privateKey->p);
1253  TRACE_DEBUG(" Prime 2:\r\n");
1254  TRACE_DEBUG_MPI(" ", &privateKey->q);
1255  TRACE_DEBUG(" Prime exponent 1:\r\n");
1256  TRACE_DEBUG_MPI(" ", &privateKey->dp);
1257  TRACE_DEBUG(" Prime exponent 2:\r\n");
1258  TRACE_DEBUG_MPI(" ", &privateKey->dq);
1259  TRACE_DEBUG(" Coefficient:\r\n");
1260  TRACE_DEBUG_MPI(" ", &privateKey->qinv);
1261  }
1262  }
1263  else
1264  {
1265  //The private key is not valid
1266  error = ERROR_INVALID_KEY;
1267  }
1268  }
1269  else
1270 #endif
1271  //Invalid algorithm identifier?
1272  {
1273  //Report an error
1274  error = ERROR_WRONG_IDENTIFIER;
1275  }
1276 
1277  //Return status code
1278  return error;
1279 }
1280 
1281 
1282 /**
1283  * @brief Import a DSA private key
1284  * @param[out] privateKey DSA private key
1285  * @param[in] privateKeyInfo Private key information
1286  * @return Error code
1287  **/
1288 
1290  const Pkcs8PrivateKeyInfo *privateKeyInfo)
1291 {
1292  error_t error;
1293 
1294 #if (DSA_SUPPORT == ENABLED)
1295  //DSA algorithm identifier?
1296  if(OID_COMP(privateKeyInfo->oid.value, privateKeyInfo->oid.length,
1297  DSA_OID) == 0)
1298  {
1299  //Sanity check
1300  if(privateKeyInfo->dsaParams.p.value != NULL &&
1301  privateKeyInfo->dsaParams.q.value != NULL &&
1302  privateKeyInfo->dsaParams.g.value != NULL &&
1303  privateKeyInfo->dsaPrivateKey.x.value != NULL)
1304  {
1305  //Read parameter p
1306  error = mpiImport(&privateKey->params.p,
1307  privateKeyInfo->dsaParams.p.value,
1308  privateKeyInfo->dsaParams.p.length, MPI_FORMAT_BIG_ENDIAN);
1309 
1310  //Check status code
1311  if(!error)
1312  {
1313  //Read parameter q
1314  error = mpiImport(&privateKey->params.q,
1315  privateKeyInfo->dsaParams.q.value,
1316  privateKeyInfo->dsaParams.q.length, MPI_FORMAT_BIG_ENDIAN);
1317  }
1318 
1319  //Check status code
1320  if(!error)
1321  {
1322  //Read parameter g
1323  error = mpiImport(&privateKey->params.g,
1324  privateKeyInfo->dsaParams.g.value,
1325  privateKeyInfo->dsaParams.g.length, MPI_FORMAT_BIG_ENDIAN);
1326  }
1327 
1328  //Check status code
1329  if(!error)
1330  {
1331  //Read private value
1332  error = mpiImport(&privateKey->x,
1333  privateKeyInfo->dsaPrivateKey.x.value,
1334  privateKeyInfo->dsaPrivateKey.x.length, MPI_FORMAT_BIG_ENDIAN);
1335  }
1336 
1337  //Check status code
1338  if(!error)
1339  {
1340  //The public key is optional
1341  if(privateKeyInfo->dsaPublicKey.y.value != NULL)
1342  {
1343  //Read public value
1344  error = mpiImport(&privateKey->y,
1345  privateKeyInfo->dsaPublicKey.y.value,
1346  privateKeyInfo->dsaPublicKey.y.length, MPI_FORMAT_BIG_ENDIAN);
1347  }
1348  else
1349  {
1350  //The public key is not present
1351  mpiFree(&privateKey->y);
1352  mpiInit(&privateKey->y);
1353  }
1354  }
1355 
1356  //Check status code
1357  if(!error)
1358  {
1359  //Dump DSA private key
1360  TRACE_DEBUG("DSA private key:\r\n");
1361  TRACE_DEBUG(" Parameter p:\r\n");
1362  TRACE_DEBUG_MPI(" ", &privateKey->params.p);
1363  TRACE_DEBUG(" Parameter q:\r\n");
1364  TRACE_DEBUG_MPI(" ", &privateKey->params.q);
1365  TRACE_DEBUG(" Parameter g:\r\n");
1366  TRACE_DEBUG_MPI(" ", &privateKey->params.g);
1367  TRACE_DEBUG(" Private value x:\r\n");
1368  TRACE_DEBUG_MPI(" ", &privateKey->x);
1369  TRACE_DEBUG(" Public value y:\r\n");
1370  TRACE_DEBUG_MPI(" ", &privateKey->y);
1371  }
1372  }
1373  else
1374  {
1375  //The private key is not valid
1376  error = ERROR_INVALID_KEY;
1377  }
1378  }
1379  else
1380 #endif
1381  //Invalid algorithm identifier?
1382  {
1383  //Report an error
1384  error = ERROR_WRONG_IDENTIFIER;
1385  }
1386 
1387  //Return status code
1388  return error;
1389 }
1390 
1391 
1392 /**
1393  * @brief Import an EC private key
1394  * @param[out] privateKey EC private key
1395  * @param[in] privateKeyInfo Private key information
1396  * @return Error code
1397  **/
1398 
1400  const Pkcs8PrivateKeyInfo *privateKeyInfo)
1401 {
1402  error_t error;
1403 
1404 #if (EC_SUPPORT == ENABLED)
1405  //EC public key algorithm identifier?
1406  if(OID_COMP(privateKeyInfo->oid.value, privateKeyInfo->oid.length,
1407  EC_PUBLIC_KEY_OID) == 0)
1408  {
1409  //Sanity check
1410  if(privateKeyInfo->ecParams.namedCurve.value != NULL &&
1411  privateKeyInfo->ecPrivateKey.d.value != NULL)
1412  {
1413  const EcCurve *curve;
1414 
1415  //Get the elliptic curve that matches the OID
1416  curve = ecGetCurve(privateKeyInfo->ecParams.namedCurve.value,
1417  privateKeyInfo->ecParams.namedCurve.length);
1418 
1419  //Make sure the specified elliptic curve is supported
1420  if(curve != NULL)
1421  {
1422  //Read the EC private key
1423  error = ecImportPrivateKey(privateKey, curve,
1424  privateKeyInfo->ecPrivateKey.d.value,
1425  privateKeyInfo->ecPrivateKey.d.length);
1426 
1427  //Check status code
1428  if(!error)
1429  {
1430  //The public key is optional
1431  if(privateKeyInfo->ecPublicKey.q.value != NULL)
1432  {
1433  //Read the EC public key
1434  error = ecImportPublicKey(&privateKey->q, curve,
1435  privateKeyInfo->ecPublicKey.q.value,
1436  privateKeyInfo->ecPublicKey.q.length,
1438  }
1439  else
1440  {
1441  //The EC public key is not present
1442  ecInitPublicKey(&privateKey->q);
1443  }
1444  }
1445  }
1446  else
1447  {
1448  //Invalid elliptic curve
1449  error = ERROR_WRONG_IDENTIFIER;
1450  }
1451 
1452  //Check status code
1453  if(!error)
1454  {
1455  //Dump EC private key
1456  TRACE_DEBUG("EC private key:\r\n");
1457  TRACE_DEBUG_EC_SCALAR(" ", privateKey->d, (curve->orderSize + 31) / 32);
1458 
1459  //Valid public key?
1460  if(privateKey->q.curve != NULL)
1461  {
1462  //Dump EC public key
1463  TRACE_DEBUG("EC public key X:\r\n");
1464  TRACE_DEBUG_EC_SCALAR(" ", privateKey->q.q.x, (curve->fieldSize + 31) / 32);
1465  TRACE_DEBUG("EC public key Y:\r\n");
1466  TRACE_DEBUG_EC_SCALAR(" ", privateKey->q.q.y, (curve->fieldSize + 31) / 32);
1467  }
1468  }
1469  }
1470  else
1471  {
1472  //The private key is not valid
1473  error = ERROR_INVALID_KEY;
1474  }
1475  }
1476  else
1477 #endif
1478  //Invalid algorithm identifier?
1479  {
1480  //Report an error
1481  error = ERROR_WRONG_IDENTIFIER;
1482  }
1483 
1484  //Return status code
1485  return error;
1486 }
1487 
1488 
1489 /**
1490  * @brief Import an EdDSA private key
1491  * @param[out] privateKey EdDSA private key
1492  * @param[in] privateKeyInfo Private key information
1493  * @return Error code
1494  **/
1495 
1497  const Pkcs8PrivateKeyInfo *privateKeyInfo)
1498 {
1499 #if (ED25519_SUPPORT == ENABLED || ED448_SUPPORT == ENABLED)
1500  error_t error;
1501  const EcCurve *curve;
1502 
1503  //Get the elliptic curve that matches the OID
1504  curve = ecGetCurve(privateKeyInfo->oid.value, privateKeyInfo->oid.length);
1505 
1506  //Edwards elliptic curve?
1507  if(curve != NULL && curve->type == EC_CURVE_TYPE_EDWARDS)
1508  {
1509  //Read the EdDSA private key
1510  error = eddsaImportPrivateKey(privateKey, curve,
1511  privateKeyInfo->eddsaPrivateKey.d.value,
1512  privateKeyInfo->eddsaPrivateKey.d.length);
1513 
1514  //Check status code
1515  if(!error)
1516  {
1517  //The public key is optional
1518  if(privateKeyInfo->eddsaPublicKey.q.value != NULL)
1519  {
1520  //Read the EdDSA public key
1521  error = eddsaImportPublicKey(&privateKey->q, curve,
1522  privateKeyInfo->eddsaPublicKey.q.value,
1523  privateKeyInfo->eddsaPublicKey.q.length);
1524  }
1525  else
1526  {
1527  //The EdDSA public key is not present
1528  eddsaInitPublicKey(&privateKey->q);
1529  }
1530  }
1531  }
1532  else
1533  {
1534  //Report an error
1535  error = ERROR_WRONG_IDENTIFIER;
1536  }
1537 
1538  //Check status code
1539  if(!error)
1540  {
1541  //Dump EdDSA private key
1542  TRACE_DEBUG("EdDSA private key:\r\n");
1543  TRACE_DEBUG_ARRAY(" ", privateKey->d, privateKeyInfo->eddsaPrivateKey.d.length);
1544 
1545  //Valid public key?
1546  if(privateKey->q.curve != NULL)
1547  {
1548  //Dump EdDSA public key
1549  TRACE_DEBUG("EdDSA public key:\r\n");
1550  TRACE_DEBUG_ARRAY(" ", privateKey->q.q, privateKeyInfo->eddsaPublicKey.q.length);
1551  }
1552  }
1553 
1554  //Return status code
1555  return error;
1556 #else
1557  //Not implemented
1558  return ERROR_NOT_IMPLEMENTED;
1559 #endif
1560 }
1561 
1562 
1563 /**
1564  * @brief Import an ML-DSA private key
1565  * @param[out] privateKey ML-DSA private key
1566  * @param[in] privateKeyInfo Private key information
1567  * @return Error code
1568  **/
1569 
1571  const Pkcs8PrivateKeyInfo *privateKeyInfo)
1572 {
1573 #if (MLDSA44_SUPPORT == ENABLED || MLDSA65_SUPPORT == ENABLED || \
1574  MLDSA87_SUPPORT == ENABLED)
1575  error_t error;
1576  uint_t level;
1577 
1578  //Initialize status code
1579  error = NO_ERROR;
1580 
1581  //Check algorithm identifier
1582  if(OID_COMP(privateKeyInfo->oid.value, privateKeyInfo->oid.length,
1583  MLDSA44_OID) == 0)
1584  {
1585  //ML-DSA-44
1586  level = MLDSA44_SECURITY_LEVEL;
1587  }
1588  else if(OID_COMP(privateKeyInfo->oid.value, privateKeyInfo->oid.length,
1589  MLDSA65_OID) == 0)
1590  {
1591  //ML-DSA-65
1592  level = MLDSA65_SECURITY_LEVEL;
1593  }
1594  else if(OID_COMP(privateKeyInfo->oid.value, privateKeyInfo->oid.length,
1595  MLDSA87_OID) == 0)
1596  {
1597  //ML-DSA-87
1598  level = MLDSA87_SECURITY_LEVEL;
1599  }
1600  else
1601  {
1602  //Invalid algorithm identifier
1603  error = ERROR_WRONG_IDENTIFIER;
1604  }
1605 
1606  //Check status code
1607  if(!error)
1608  {
1609  //Valid seed?
1610  if(privateKeyInfo->mldsaPrivateKey.seed.length > 0)
1611  {
1612  //Read the seed
1613  error = mldsaImportSeed(privateKey, level,
1614  privateKeyInfo->mldsaPrivateKey.seed.value,
1615  privateKeyInfo->mldsaPrivateKey.seed.length);
1616  }
1617  }
1618 
1619  //Check status code
1620  if(!error)
1621  {
1622  //Valid expanded key?
1623  if(privateKeyInfo->mldsaPrivateKey.expandedKey.length > 0)
1624  {
1625  //Read the expanded key
1626  error = mldsaImportPrivateKey(privateKey, level,
1627  privateKeyInfo->mldsaPrivateKey.expandedKey.value,
1628  privateKeyInfo->mldsaPrivateKey.expandedKey.length);
1629  }
1630  }
1631 
1632  //Check status code
1633  if(!error)
1634  {
1635  //Dump ML-DSA private key
1636  TRACE_DEBUG("ML-DSA private key:\r\n");
1637 
1638  //Valid seed?
1639  if(privateKey->seed != NULL)
1640  {
1641  TRACE_DEBUG(" Seed:\r\n");
1642  TRACE_DEBUG_ARRAY(" ", privateKey->seed,
1643  privateKeyInfo->mldsaPrivateKey.seed.length);
1644  }
1645 
1646  //Valid secret key?
1647  if(privateKey->sk != NULL)
1648  {
1649  TRACE_DEBUG(" Expanded key:\r\n");
1650  TRACE_DEBUG_ARRAY(" ", privateKey->sk,
1651  privateKeyInfo->mldsaPrivateKey.expandedKey.length);
1652  }
1653  }
1654 
1655  //Return status code
1656  return error;
1657 #else
1658  //Not implemented
1659  return ERROR_NOT_IMPLEMENTED;
1660 #endif
1661 }
1662 
1663 #endif
error_t mldsaImportPrivateKey(MldsaPrivateKey *key, uint_t level, const uint8_t *input, size_t length)
Import an ML-DSA private key.
Definition: mldsa.c:276
const uint8_t MLDSA44_OID[9]
Definition: mldsa.c:47
Pkcs8MldsaPrivateKey mldsaPrivateKey
X509OctetString dq
error_t pkcs8ParsePrivateKeyInfo(const uint8_t *data, size_t length, Pkcs8PrivateKeyInfo *privateKeyInfo)
Parse PrivateKeyInfo structure.
Pkcs8RsaPrivateKey rsaPrivateKey
@ PKCS8_VERSION_2
Definition: x509_common.h:526
@ EC_CURVE_TYPE_EDWARDS
Definition: ec.h:364
Private key information.
X509OctetString params
Definition: x509_common.h:806
Mpi p
First factor.
Definition: rsa.h:72
uint8_t d[EDDSA_MAX_PRIVATE_KEY_LEN]
Private key.
Definition: eddsa.h:77
const uint8_t X25519_OID[3]
Definition: ec_curves.c:108
EdDSA public key.
X509OctetString g
Definition: x509_common.h:829
const uint8_t MLDSA65_OID[9]
Definition: mldsa.c:49
X509OctetString p
Definition: x509_common.h:827
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
uint8_t * seed
Seed.
Definition: mldsa.h:96
OID (Object Identifier)
Mpi q
Group order.
Definition: dsa.h:51
uint8_t data[]
Definition: ethernet.h:224
const uint8_t EC_PUBLIC_KEY_OID[7]
Definition: ec.c:44
Encrypted private key information.
error_t ecImportPublicKey(EcPublicKey *key, const EcCurve *curve, const uint8_t *input, size_t length, EcPublicKeyFormat format)
Import an EC public key.
Definition: ec.c:263
Mpi n
Modulus.
Definition: rsa.h:69
error_t mldsaImportSeed(MldsaPrivateKey *key, uint_t level, const uint8_t *input, size_t length)
Import an ML-DSA seed.
Definition: mldsa.c:408
ML-DSA private key.
RSA private key.
X509DsaPublicKey dsaPublicKey
X509OctetString d
#define TRACE_DEBUG_EC_SCALAR(p, a, n)
Definition: debug.h:123
#define MLDSA87_SECURITY_LEVEL
Definition: mldsa.h:61
@ EC_PUBLIC_KEY_FORMAT_X963
Definition: ec.h:386
uint16_t totalLength
Definition: ipv4.h:348
Mpi p
Prime modulus.
Definition: dsa.h:50
error_t pkcs8ImportDsaPrivateKey(DsaPrivateKey *privateKey, const Pkcs8PrivateKeyInfo *privateKeyInfo)
Import a DSA private key.
const uint8_t RSASSA_PSS_OID[9]
Definition: rsa.c:85
uint8_t version
Definition: coap_common.h:177
error_t asn1ReadTag(const uint8_t *data, size_t length, Asn1Tag *tag)
Read an ASN.1 tag from the input stream.
Definition: asn1.c:52
uint32_t y[EC_MAX_MODULUS_SIZE]
y-coordinate
Definition: ec.h:400
#define MLDSA65_SECURITY_LEVEL
Definition: mldsa.h:50
error_t x509ParseDsaParameters(const uint8_t *data, size_t length, X509DsaParameters *dsaParams)
Parse DSA domain parameters.
error_t pkcs8ParseEddsaPublicKey(const uint8_t *data, size_t length, Pkcs8EddsaPublicKey *eddsaPublicKey)
Parse publicKey structure.
@ ERROR_INVALID_VERSION
Definition: error.h:118
void mpiInit(Mpi *r)
Initialize a multiple precision integer.
Definition: mpi.c:49
uint8_t oid[]
Definition: lldp_tlv.h:300
Mpi d
Private exponent.
Definition: rsa.h:71
EdDSA private key.
X509OctetString q
Definition: x509_common.h:828
error_t asn1ReadOid(const uint8_t *data, size_t length, Asn1Tag *tag)
Read an object identifier from the input stream.
Definition: asn1.c:218
EC public key.
Definition: x509_common.h:858
const uint8_t DSA_OID[7]
Definition: dsa.c:51
X509OctetString n
size_t totalLength
Definition: asn1.h:111
size_t length
Definition: asn1.h:109
X509OctetString y
Definition: x509_common.h:839
Pkcs8EcPrivateKey ecPrivateKey
#define MLDSA44_SECURITY_LEVEL
Definition: mldsa.h:39
#define FALSE
Definition: os_port.h:46
error_t asn1ReadOctetString(const uint8_t *data, size_t length, Asn1Tag *tag)
Read an octet string from the input stream.
Definition: asn1.c:190
error_t pkcs8ParsePrivateKeyAlgo(const uint8_t *data, size_t length, size_t *totalLength, Pkcs8PrivateKeyInfo *privateKeyInfo)
Parse PrivateKeyAlgorithm structure.
error_t pkcs8ParseEddsaPrivateKey(const uint8_t *data, size_t length, Pkcs8EddsaPrivateKey *eddsaPrivateKey)
Parse CurvePrivateKey structure.
uint8_t q[EDDSA_MAX_PUBLIC_KEY_LEN]
Public key.
Definition: eddsa.h:66
const EcCurve * curve
Elliptic curve parameters.
Definition: eddsa.h:65
error_t
Error codes.
Definition: error.h:43
Mpi g
Group generator.
Definition: dsa.h:52
EC parameters.
Definition: x509_common.h:848
X509OctetString dp
void ecInitPublicKey(EcPublicKey *key)
Initialize an EC public key.
Definition: ec.c:52
X509OctetString e
#define ASN1_CLASS_UNIVERSAL
Definition: asn1.h:52
error_t pkcs8ImportRsaPrivateKey(RsaPrivateKey *privateKey, const Pkcs8PrivateKeyInfo *privateKeyInfo)
Import an RSA private key.
uint8_t * sk
Secret key.
Definition: mldsa.h:98
ASN.1 tag.
Definition: asn1.h:105
Mpi q
Second factor.
Definition: rsa.h:73
Helper routines for ECC.
X509OctetString p
error_t mpiImport(Mpi *r, const uint8_t *input, size_t length, MpiFormat format)
Octet string to integer conversion.
Definition: mpi.c:714
error_t asn1ReadInt32(const uint8_t *data, size_t length, Asn1Tag *tag, int32_t *value)
Read a 32-bit integer from the input stream.
Definition: asn1.c:285
X509EcPublicKey ecPublicKey
X509DsaParameters dsaParams
X509OctetString oid
Definition: x509_common.h:805
error_t ecImportPrivateKey(EcPrivateKey *key, const EcCurve *curve, const uint8_t *input, size_t length)
Import an EC private key.
Definition: ec.c:514
Pkcs8EddsaPublicKey eddsaPublicKey
General definitions for cryptographic algorithms.
Mpi y
Public key value.
Definition: dsa.h:75
EcPublicKey q
Public key.
Definition: ec.h:436
X509OctetString q
EC private key.
Definition: ec.h:432
Pkcs8EddsaPrivateKey eddsaPrivateKey
DSA private key.
Definition: dsa.h:72
uint_t objClass
Definition: asn1.h:107
uint8_t length
Definition: tcp.h:375
error_t pkcs8ParseRsaPrivateKey(const uint8_t *data, size_t length, Pkcs8RsaPrivateKey *rsaPrivateKey)
Parse RSAPrivateKey structure.
@ PKCS8_VERSION_1
Definition: x509_common.h:525
Mpi e
Public exponent.
Definition: rsa.h:70
error_t asn1CheckOid(const Asn1Tag *tag, const uint8_t *oid, size_t length)
Check ASN.1 tag against a specified OID.
Definition: asn1.c:972
error_t pkcs8ParseDsaPrivateKey(const uint8_t *data, size_t length, X509DsaParameters *dsaParams, Pkcs8DsaPrivateKey *dsaPrivateKey, X509DsaPublicKey *dsaPublicKey)
Parse DSAPrivateKey structure.
error_t pkcs8ParseEncryptionAlgoId(const uint8_t *data, size_t length, size_t *totalLength, X509AlgoId *encryptionAlgoId)
Parse EncryptionAlgorithmIdentifier structure.
X509OctetString seed
X509OctetString namedCurve
Definition: x509_common.h:849
const uint8_t ED448_OID[3]
Definition: ec_curves.c:114
Mpi qinv
CRT coefficient.
Definition: rsa.h:76
EdDSA private key.
Definition: eddsa.h:75
Mpi dq
Second factor's CRT exponent.
Definition: rsa.h:75
const uint8_t ED25519_OID[3]
Definition: ec_curves.c:112
const uint8_t RSA_ENCRYPTION_OID[9]
Definition: rsa.c:54
const uint8_t X448_OID[3]
Definition: ec_curves.c:110
@ ASN1_TYPE_OCTET_STRING
Definition: asn1.h:75
@ ASN1_TYPE_INTEGER
Definition: asn1.h:73
#define TRACE_DEBUG(...)
Definition: debug.h:119
error_t pkcs8ImportEddsaPrivateKey(EddsaPrivateKey *privateKey, const Pkcs8PrivateKeyInfo *privateKeyInfo)
Import an EdDSA private key.
error_t pkcs8ImportEcPrivateKey(EcPrivateKey *privateKey, const Pkcs8PrivateKeyInfo *privateKeyInfo)
Import an EC private key.
X509OctetString d
#define TRACE_DEBUG_ARRAY(p, a, n)
Definition: debug.h:120
X509OctetString d
error_t pkcs8ParseMldsaPrivateKey(const uint8_t *data, size_t length, Pkcs8MldsaPrivateKey *mldsaPrivateKey)
Parse ML-DSA-PrivateKey structure.
X509OctetString q
Definition: x509_common.h:859
uint32_t d[EC_MAX_ORDER_SIZE]
Private key.
Definition: ec.h:434
#define OID_COMP(oid1, oidLen1, oid2)
Definition: oid.h:42
uint8_t n
RSA private key.
Definition: rsa.h:68
error_t pkcs8ParseEncryptedPrivateKeyInfo(const uint8_t *data, size_t length, Pkcs8EncryptedPrivateKeyInfo *encryptedPrivateKeyInfo)
Parse EncryptedPrivateKeyInfo structure.
DSA domain parameters.
Definition: x509_common.h:826
#define ASN1_CLASS_CONTEXT_SPECIFIC
Definition: asn1.h:54
X509OctetString qinv
X509OctetString expandedKey
PKCS #8 key parsing.
Mpi x
Secret exponent.
Definition: dsa.h:74
EcPoint q
Public key.
Definition: ec.h:423
uint8_t oidLen
Definition: lldp_tlv.h:299
@ MPI_FORMAT_BIG_ENDIAN
Definition: mpi.h:93
bool_t constructed
Definition: asn1.h:106
@ ERROR_WRONG_IDENTIFIER
Definition: error.h:89
ML-DSA private key.
Definition: mldsa.h:94
@ ERROR_INVALID_SYNTAX
Definition: error.h:68
@ ASN1_TYPE_SEQUENCE
Definition: asn1.h:83
EddsaPublicKey q
Public key.
Definition: eddsa.h:79
error_t x509ParseEcParameters(const uint8_t *data, size_t length, X509EcParameters *ecParams)
Parse ECParameters structure.
const EcCurve * ecGetCurve(const uint8_t *oid, size_t length)
Get the elliptic curve that matches the specified OID.
Definition: ec_curves.c:5888
@ ERROR_WRONG_ENCODING
Definition: error.h:122
DsaDomainParameters params
DSA domain parameters.
Definition: dsa.h:73
const uint8_t * value
Definition: x509_common.h:732
error_t eddsaImportPublicKey(EddsaPublicKey *key, const EcCurve *curve, const uint8_t *input, size_t length)
Import an EdDSA public key.
Definition: eddsa.c:275
X509OctetString q
#define EcCurve
Definition: ec.h:346
Mpi dp
First factor's CRT exponent.
Definition: rsa.h:74
Parsing of ASN.1 encoded keys.
Pkcs8DsaPrivateKey dsaPrivateKey
@ ASN1_TYPE_BIT_STRING
Definition: asn1.h:74
error_t pkcs8ImportMldsaPrivateKey(MldsaPrivateKey *privateKey, const Pkcs8PrivateKeyInfo *privateKeyInfo)
Import an ML-DSA private key.
@ ERROR_INVALID_CLASS
Definition: error.h:117
error_t eddsaImportPrivateKey(EddsaPrivateKey *key, const EcCurve *curve, const uint8_t *input, size_t length)
Import an EdDSA private key.
Definition: eddsa.c:383
unsigned int uint_t
Definition: compiler_port.h:57
uint32_t x[EC_MAX_MODULUS_SIZE]
x-coordinate
Definition: ec.h:399
#define TRACE_DEBUG_MPI(p, a)
Definition: debug.h:122
const uint8_t MLDSA87_OID[9]
Definition: mldsa.c:51
#define osMemset(p, value, length)
Definition: os_port.h:141
EC private key.
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
DSA private key.
DSA public key.
Definition: x509_common.h:838
X509EcParameters ecParams
X509OctetString oid
void eddsaInitPublicKey(EddsaPublicKey *key)
Initialize an EdDSA public key.
Definition: eddsa.c:48
error_t pkcs8ParseEcPrivateKey(const uint8_t *data, size_t length, X509EcParameters *ecParams, Pkcs8EcPrivateKey *ecPrivateKey, X509EcPublicKey *ecPublicKey)
Parse ECPrivateKey structure.
const EcCurve * curve
Elliptic curve parameters.
Definition: ec.h:422
X509OctetString x
const uint8_t * value
Definition: asn1.h:110
error_t pkcs8ParseEcPublicKey(const uint8_t *data, size_t length, X509EcPublicKey *ecPublicKey)
Parse publicKey structure.
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:944
@ ERROR_INVALID_KEY
Definition: error.h:106
Algorithm identifier.
Definition: x509_common.h:804
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
uint_t objType
Definition: asn1.h:108
ASN.1 (Abstract Syntax Notation One)
void mpiFree(Mpi *r)
Release a multiple precision integer.
Definition: mpi.c:65