pkcs8_key_format.c
Go to the documentation of this file.
1 /**
2  * @file pkcs8_key_format.c
3  * @brief PKCS #8 key formatting
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 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.5.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/crypto.h"
36 #include "pkix/pkcs8_key_format.h"
37 #include "pkix/x509_key_format.h"
38 #include "encoding/asn1.h"
39 #include "encoding/oid.h"
40 #include "ecc/ec_misc.h"
41 #include "debug.h"
42 
43 //Check crypto library configuration
44 #if (PEM_SUPPORT == ENABLED)
45 
46 
47 /**
48  * @brief Format an RSA private key
49  * @param[in] privateKey Pointer to the RSA private key
50  * @param[out] output Buffer where to store the ASN.1 structure
51  * @param[out] written Length of the resulting ASN.1 structure
52  * @return Error code
53  **/
54 
56  uint8_t *output, size_t *written)
57 {
58  error_t error;
59  size_t n;
60  Asn1Tag tag;
61 
62  //Export the RSA private key to ASN.1 format
63  error = x509ExportRsaPrivateKey(privateKey, output, &n);
64 
65  //Check status code
66  if(!error)
67  {
68  //The RSAPrivateKey structure is encapsulated within an octet string
69  tag.constructed = FALSE;
72  tag.length = n;
73  tag.value = output;
74 
75  //Write PrivateKey structure
76  error = asn1WriteTag(&tag, FALSE, output, written);
77  }
78 
79  //Return status code
80  return error;
81 }
82 
83 
84 /**
85  * @brief Format a DSA private key
86  * @param[in] privateKey Pointer to the RSA private key
87  * @param[out] output Buffer where to store the ASN.1 structure
88  * @param[out] written Length of the resulting ASN.1 structure
89  * @return Error code
90  **/
91 
93  uint8_t *output, size_t *written)
94 {
95  error_t error;
96  size_t n;
97  Asn1Tag tag;
98 
99  //Export the DSA private key to ASN.1 format
100  error = x509ExportDsaPrivateKey(privateKey, output, &n);
101 
102  //Check status code
103  if(!error)
104  {
105  //The DSAPrivateKey structure is encapsulated within an octet string
106  tag.constructed = FALSE;
109  tag.length = n;
110  tag.value = output;
111 
112  //Write PrivateKey structure
113  error = asn1WriteTag(&tag, FALSE, output, written);
114  }
115 
116  //Return status code
117  return error;
118 }
119 
120 
121 /**
122  * @brief Format an EC private key
123  * @param[in] privateKey EC private key
124  * @param[out] output Buffer where to format the ASN.1 structure
125  * @param[out] written Length of the resulting ASN.1 structure
126  * @return Error code
127  **/
128 
130  uint8_t *output, size_t *written)
131 {
132 #if (EC_SUPPORT == ENABLED)
133  error_t error;
134  size_t n;
135  size_t length;
136  uint8_t *p;
137  Asn1Tag tag;
138 
139  //Point to the buffer where to write the ASN.1 structure
140  p = output;
141  //Length of the ASN.1 structure
142  length = 0;
143 
144  //Format Version field (refer to RFC 5915, section 3)
145  error = asn1WriteInt32(1, FALSE, p, &n);
146  //Any error to report?
147  if(error)
148  return error;
149 
150  //Update the length of the ECPrivateKey structure
151  length += n;
152 
153  //If the output parameter is NULL, then the function calculates the
154  //length of the resulting PEM file without copying any data
155  if(output != NULL)
156  {
157  //Advance data pointer
158  p += n;
159 
160  //The PrivateKey field is an octet string of length ceiling (log2(n)/8)
161  //(refer to RFC 5915, section 3)
162  error = ecExportPrivateKey(privateKey, p, &n);
163  //Any error to report?
164  if(error)
165  return error;
166  }
167 
168  //Format PrivateKey field
169  tag.constructed = FALSE;
172  tag.length = n;
173  tag.value = p;
174 
175  //Write the corresponding ASN.1 tag
176  error = asn1WriteTag(&tag, FALSE, p, &n);
177  //Any error to report?
178  if(error)
179  return error;
180 
181  //Update the length of the ECPrivateKey structure
182  n = tag.totalLength;
183  length += n;
184 
185  //Advance data pointer
186  if(output != NULL)
187  p += n;
188 
189  //The public key is optional
190  if(privateKey->q.curve != NULL)
191  {
192  //Format PublicKey field
193  error = pkcs8FormatEcPublicKey(&privateKey->q, p, &n);
194  //Any error to report?
195  if(error)
196  return error;
197 
198  //Update the length of the ECPrivateKey structure
199  length += n;
200  }
201 
202  //Format ECPrivateKey field
203  tag.constructed = TRUE;
206  tag.length = length;
207  tag.value = output;
208 
209  //Write the corresponding ASN.1 tag
210  error = asn1WriteTag(&tag, FALSE, output, &n);
211  //Any error to report?
212  if(error)
213  return error;
214 
215  //Get the length of the ECPrivateKey structure
216  n = tag.totalLength;
217 
218  //The PrivateKey field is an octet string whose contents are the value
219  //of the private key
220  tag.constructed = FALSE;
223  tag.length = n;
224  tag.value = output;
225 
226  //Write the corresponding ASN.1 tag
227  error = asn1WriteTag(&tag, FALSE, output, &n);
228  //Any error to report?
229  if(error)
230  return error;
231 
232  //Total number of bytes that have been written
233  *written = tag.totalLength;
234 
235  //Successful processing
236  return NO_ERROR;
237 #else
238  //Not implemented
239  return ERROR_NOT_IMPLEMENTED;
240 #endif
241 }
242 
243 
244 /**
245  * @brief Format an EC public key
246  * @param[in] publicKey EC public key
247  * @param[out] output Buffer where to format the ASN.1 structure
248  * @param[out] written Length of the resulting ASN.1 structure
249  * @return Error code
250  **/
251 
253  uint8_t *output, size_t *written)
254 {
255 #if (EC_SUPPORT == ENABLED)
256  error_t error;
257  size_t n;
258  Asn1Tag tag;
259 
260  //The bit string shall contain an initial octet which encodes the number
261  //of unused bits in the final subsequent octet
262  output[0] = 0;
263 
264  //Format ECPublicKey structure
265  error = ecExportPublicKey(publicKey, output + 1, &n,
267 
268  //Check status code
269  if(!error)
270  {
271  //The public key is encapsulated within a bit string
272  tag.constructed = FALSE;
275  tag.length = n + 1;
276  tag.value = output;
277 
278  //Write the corresponding ASN.1 tag
279  error = asn1WriteTag(&tag, FALSE, output, &n);
280  }
281 
282  //Check status code
283  if(!error)
284  {
285  //Explicit tagging shall be used to encode the public key
286  tag.constructed = TRUE;
288  tag.objType = 1;
289  tag.length = n;
290  tag.value = output;
291 
292  //Write the corresponding ASN.1 tag
293  error = asn1WriteTag(&tag, FALSE, output, written);
294  }
295 
296  //Return status code
297  return error;
298 #else
299  //Not implemented
300  return ERROR_NOT_IMPLEMENTED;
301 #endif
302 }
303 
304 
305 /**
306  * @brief Format an EdDSA private key
307  * @param[in] privateKey EdDSA private key
308  * @param[out] output Buffer where to format the ASN.1 structure
309  * @param[out] written Length of the resulting ASN.1 structure
310  * @return Error code
311  **/
312 
314  uint8_t *output, size_t *written)
315 {
316 #if (ED25519_SUPPORT == ENABLED || ED448_SUPPORT == ENABLED)
317  error_t error;
318  size_t n;
319  Asn1Tag tag;
320 
321  //Export the EdDSA private key to ASN.1 format
322  error = x509ExportEddsaPrivateKey(privateKey, output, &n);
323 
324  //Check status code
325  if(!error)
326  {
327  //The CurvePrivateKey structure is encapsulated within an octet string
328  tag.constructed = FALSE;
331  tag.length = n;
332  tag.value = output;
333 
334  //Write PrivateKey structure
335  error = asn1WriteTag(&tag, FALSE, output, written);
336  }
337 
338  //Return status code
339  return error;
340 #else
341  //Not implemented
342  return ERROR_NOT_IMPLEMENTED;
343 #endif
344 }
345 
346 
347 /**
348  * @brief Format an EdDSA public key
349  * @param[in] publicKey EdDSA public key
350  * @param[out] output Buffer where to format the ASN.1 structure
351  * @param[out] written Length of the resulting ASN.1 structure
352  * @return Error code
353  **/
354 
356  uint8_t *output, size_t *written)
357 {
358 #if (ED25519_SUPPORT == ENABLED || ED448_SUPPORT == ENABLED)
359  error_t error;
360  size_t n;
361  Asn1Tag tag;
362 
363  //The bit string shall contain an initial octet which encodes the number
364  //of unused bits in the final subsequent octet
365  output[0] = 0;
366 
367  //Format EdDSA public key
368  error = eddsaExportPublicKey(publicKey, output + 1, &n);
369 
370  //Check status code
371  if(!error)
372  {
373  //Explicit tagging shall be used to encode the public key
374  tag.constructed = TRUE;
376  tag.objType = 1;
377  tag.length = n + 1;
378  tag.value = output;
379 
380  //Write the corresponding ASN.1 tag
381  error = asn1WriteTag(&tag, FALSE, output, written);
382  }
383 
384  //Return status code
385  return error;
386 #else
387  //Not implemented
388  return ERROR_NOT_IMPLEMENTED;
389 #endif
390 }
391 
392 #endif
PKCS #8 key formatting.
error_t x509ExportEddsaPrivateKey(const EddsaPrivateKey *privateKey, uint8_t *output, size_t *written)
Export an EdDSA private key to ASN.1 format.
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
error_t eddsaExportPublicKey(const EddsaPublicKey *key, uint8_t *data, size_t *length)
Export an EdDSA public key.
Definition: eddsa.c:327
OID (Object Identifier)
uint8_t p
Definition: ndp.h:300
#define TRUE
Definition: os_port.h:50
error_t pkcs8FormatEddsaPrivateKey(const EddsaPrivateKey *privateKey, uint8_t *output, size_t *written)
Format an EdDSA private key.
error_t pkcs8FormatRsaPrivateKey(const RsaPrivateKey *privateKey, uint8_t *output, size_t *written)
Format an RSA private key.
@ EC_PUBLIC_KEY_FORMAT_X963
Definition: ec.h:386
error_t pkcs8FormatDsaPrivateKey(const DsaPrivateKey *privateKey, uint8_t *output, size_t *written)
Format a DSA private key.
error_t pkcs8FormatEcPublicKey(const EcPublicKey *publicKey, uint8_t *output, size_t *written)
Format an EC public key.
size_t totalLength
Definition: asn1.h:108
size_t length
Definition: asn1.h:106
#define FALSE
Definition: os_port.h:46
error_t
Error codes.
Definition: error.h:43
error_t ecExportPrivateKey(const EcPrivateKey *key, uint8_t *data, size_t *length)
Export an EC private key.
Definition: ec.c:554
error_t x509ExportDsaPrivateKey(const DsaPrivateKey *privateKey, uint8_t *output, size_t *written)
Export a DSA private key to ASN.1 format.
EdDSA public key.
Definition: eddsa.h:64
#define ASN1_CLASS_UNIVERSAL
Definition: asn1.h:52
error_t pkcs8FormatEcPrivateKey(const EcPrivateKey *privateKey, uint8_t *output, size_t *written)
Format an EC private key.
ASN.1 tag.
Definition: asn1.h:102
Helper routines for ECC.
General definitions for cryptographic algorithms.
EcPublicKey q
Public key.
Definition: ec.h:436
error_t asn1WriteTag(Asn1Tag *tag, bool_t reverse, uint8_t *data, size_t *written)
Write an ASN.1 tag.
Definition: asn1.c:334
EC private key.
Definition: ec.h:432
DSA private key.
Definition: dsa.h:72
uint_t objClass
Definition: asn1.h:104
uint8_t length
Definition: tcp.h:375
error_t x509ExportRsaPrivateKey(const RsaPrivateKey *privateKey, uint8_t *output, size_t *written)
Export an RSA private key to ASN.1 format.
error_t ecExportPublicKey(const EcPublicKey *key, uint8_t *data, size_t *length, EcPublicKeyFormat format)
Export an EC public key.
Definition: ec.c:378
EdDSA private key.
Definition: eddsa.h:75
EC public key.
Definition: ec.h:421
@ ASN1_TYPE_OCTET_STRING
Definition: asn1.h:72
Formatting of ASN.1 encoded keys.
uint8_t n
RSA private key.
Definition: rsa.h:68
#define ASN1_CLASS_CONTEXT_SPECIFIC
Definition: asn1.h:54
bool_t constructed
Definition: asn1.h:103
@ ASN1_TYPE_SEQUENCE
Definition: asn1.h:80
error_t pkcs8FormatEddsaPublicKey(const EddsaPublicKey *publicKey, uint8_t *output, size_t *written)
Format an EdDSA public key.
@ ASN1_TYPE_BIT_STRING
Definition: asn1.h:71
error_t asn1WriteInt32(int32_t value, bool_t reverse, uint8_t *data, size_t *written)
Write a 32-bit integer to the output stream.
Definition: asn1.c:645
const EcCurve * curve
Elliptic curve parameters.
Definition: ec.h:422
const uint8_t * value
Definition: asn1.h:107
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
uint_t objType
Definition: asn1.h:105
ASN.1 (Abstract Syntax Notation One)