pem_cert_key_import.c
Go to the documentation of this file.
1 /**
2  * @file pem_cert_key_import.c
3  * @brief PEM certificate public key import functions
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.2
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/crypto.h"
36 #include "pkix/pem_import.h"
38 #include "pkix/pem_decrypt.h"
39 #include "pkix/pkcs5_decrypt.h"
40 #include "pkix/pkcs8_key_parse.h"
41 #include "pkix/x509_key_parse.h"
42 #include "pkix/x509_cert_parse.h"
43 #include "debug.h"
44 
45 //Check crypto library configuration
46 #if (PEM_SUPPORT == ENABLED)
47 
48 
49 /**
50  * @brief Extract the RSA public key from a PEM certificate
51  * @param[out] publicKey RSA public key resulting from the parsing process
52  * @param[in] input Pointer to the PEM certificate
53  * @param[in] length Length of the PEM certificate
54  * @return Error code
55  **/
56 
58  size_t length)
59 {
60 #if (RSA_SUPPORT == ENABLED)
61  error_t error;
62  uint8_t *derCert;
63  size_t derCertLen;
64  X509CertInfo *certInfo;
65 
66  //The first pass calculates the length of the DER-encoded certificate
67  error = pemImportCertificate(input, length, NULL, &derCertLen,
68  NULL);
69 
70  //Check status code
71  if(!error)
72  {
73  //Allocate a memory buffer to hold the DER-encoded certificate
74  derCert = cryptoAllocMem(derCertLen);
75 
76  //Successful memory allocation?
77  if(derCert != NULL)
78  {
79  //The second pass decodes the PEM certificate
80  error = pemImportCertificate(input, length, derCert, &derCertLen,
81  NULL);
82 
83  //Check status code
84  if(!error)
85  {
86  //Allocate a memory buffer to store X.509 certificate info
87  certInfo = cryptoAllocMem(sizeof(X509CertInfo));
88 
89  //Successful memory allocation?
90  if(certInfo != NULL)
91  {
93 
94  //Additional certificate parsing options
96  options.ignoreUnknownExtensions = TRUE;
97 
98  //Parse X.509 certificate
99  error = x509ParseCertificateEx(derCert, derCertLen, certInfo,
100  &options);
101 
102  //Check status code
103  if(!error)
104  {
105  //Import the RSA public key
106  error = x509ImportRsaPublicKey(publicKey,
107  &certInfo->tbsCert.subjectPublicKeyInfo);
108  }
109 
110  //Release previously allocated memory
111  cryptoFreeMem(certInfo);
112  }
113  else
114  {
115  //Failed to allocate memory
116  error = ERROR_OUT_OF_MEMORY;
117  }
118  }
119 
120  //Release previously allocated memory
121  cryptoFreeMem(derCert);
122  }
123  else
124  {
125  //Failed to allocate memory
126  error = ERROR_OUT_OF_MEMORY;
127  }
128  }
129 
130  //Return status code
131  return error;
132 #else
133  //Not implemented
134  return ERROR_NOT_IMPLEMENTED;
135 #endif
136 }
137 
138 
139 /**
140  * @brief Extract the DSA public key from a PEM certificate
141  * @param[out] publicKey DSA public key resulting from the parsing process
142  * @param[in] input Pointer to the PEM certificate
143  * @param[in] length Length of the PEM certificate
144  * @return Error code
145  **/
146 
148  size_t length)
149 {
150 #if (DSA_SUPPORT == ENABLED)
151  error_t error;
152  uint8_t *derCert;
153  size_t derCertLen;
154  X509CertInfo *certInfo;
155 
156  //The first pass calculates the length of the DER-encoded certificate
157  error = pemImportCertificate(input, length, NULL, &derCertLen,
158  NULL);
159 
160  //Check status code
161  if(!error)
162  {
163  //Allocate a memory buffer to hold the DER-encoded certificate
164  derCert = cryptoAllocMem(derCertLen);
165 
166  //Successful memory allocation?
167  if(derCert != NULL)
168  {
169  //The second pass decodes the PEM certificate
170  error = pemImportCertificate(input, length, derCert, &derCertLen,
171  NULL);
172 
173  //Check status code
174  if(!error)
175  {
176  //Allocate a memory buffer to store X.509 certificate info
177  certInfo = cryptoAllocMem(sizeof(X509CertInfo));
178 
179  //Successful memory allocation?
180  if(certInfo != NULL)
181  {
183 
184  //Additional certificate parsing options
186  options.ignoreUnknownExtensions = TRUE;
187 
188  //Parse X.509 certificate
189  error = x509ParseCertificateEx(derCert, derCertLen, certInfo,
190  &options);
191 
192  //Check status code
193  if(!error)
194  {
195  //Import the DSA public key
196  error = x509ImportDsaPublicKey(publicKey,
197  &certInfo->tbsCert.subjectPublicKeyInfo);
198  }
199 
200  //Release previously allocated memory
201  cryptoFreeMem(certInfo);
202  }
203  else
204  {
205  //Failed to allocate memory
206  error = ERROR_OUT_OF_MEMORY;
207  }
208  }
209 
210  //Release previously allocated memory
211  cryptoFreeMem(derCert);
212  }
213  else
214  {
215  //Failed to allocate memory
216  error = ERROR_OUT_OF_MEMORY;
217  }
218  }
219 
220  //Return status code
221  return error;
222 #else
223  //Not implemented
224  return ERROR_NOT_IMPLEMENTED;
225 #endif
226 }
227 
228 
229 /**
230  * @brief Extract the EC public key from a PEM certificate
231  * @param[out] publicKey EC public key resulting from the parsing process
232  * @param[in] input Pointer to the PEM certificate
233  * @param[in] length Length of the PEM certificate
234  * @return Error code
235  **/
236 
238  size_t length)
239 {
240 #if (EC_SUPPORT == ENABLED)
241  error_t error;
242  uint8_t *derCert;
243  size_t derCertLen;
244  X509CertInfo *certInfo;
245 
246  //The first pass calculates the length of the DER-encoded certificate
247  error = pemImportCertificate(input, length, NULL, &derCertLen,
248  NULL);
249 
250  //Check status code
251  if(!error)
252  {
253  //Allocate a memory buffer to hold the DER-encoded certificate
254  derCert = cryptoAllocMem(derCertLen);
255 
256  //Successful memory allocation?
257  if(derCert != NULL)
258  {
259  //The second pass decodes the PEM certificate
260  error = pemImportCertificate(input, length, derCert, &derCertLen,
261  NULL);
262 
263  //Check status code
264  if(!error)
265  {
266  //Allocate a memory buffer to store X.509 certificate info
267  certInfo = cryptoAllocMem(sizeof(X509CertInfo));
268 
269  //Successful memory allocation?
270  if(certInfo != NULL)
271  {
273 
274  //Additional certificate parsing options
276  options.ignoreUnknownExtensions = TRUE;
277 
278  //Parse X.509 certificate
279  error = x509ParseCertificateEx(derCert, derCertLen, certInfo,
280  &options);
281 
282  //Check status code
283  if(!error)
284  {
285  //Import the EC public key
286  error = x509ImportEcPublicKey(publicKey,
287  &certInfo->tbsCert.subjectPublicKeyInfo);
288  }
289 
290  //Release previously allocated memory
291  cryptoFreeMem(certInfo);
292  }
293  else
294  {
295  //Failed to allocate memory
296  error = ERROR_OUT_OF_MEMORY;
297  }
298  }
299 
300  //Release previously allocated memory
301  cryptoFreeMem(derCert);
302  }
303  else
304  {
305  //Failed to allocate memory
306  error = ERROR_OUT_OF_MEMORY;
307  }
308  }
309 
310  //Return status code
311  return error;
312 #else
313  //Not implemented
314  return ERROR_NOT_IMPLEMENTED;
315 #endif
316 }
317 
318 
319 /**
320  * @brief Extract the EdDSA public key from a PEM certificate
321  * @param[out] publicKey EdDSA public key resulting from the parsing process
322  * @param[in] input Pointer to the PEM certificate
323  * @param[in] length Length of the PEM certificate
324  * @return Error code
325  **/
326 
328  const char_t *input, size_t length)
329 {
330 #if (ED25519_SUPPORT == ENABLED || ED448_SUPPORT == ENABLED)
331  error_t error;
332  uint8_t *derCert;
333  size_t derCertLen;
334  X509CertInfo *certInfo;
335 
336  //The first pass calculates the length of the DER-encoded certificate
337  error = pemImportCertificate(input, length, NULL, &derCertLen,
338  NULL);
339 
340  //Check status code
341  if(!error)
342  {
343  //Allocate a memory buffer to hold the DER-encoded certificate
344  derCert = cryptoAllocMem(derCertLen);
345 
346  //Successful memory allocation?
347  if(derCert != NULL)
348  {
349  //The second pass decodes the PEM certificate
350  error = pemImportCertificate(input, length, derCert, &derCertLen,
351  NULL);
352 
353  //Check status code
354  if(!error)
355  {
356  //Allocate a memory buffer to store X.509 certificate info
357  certInfo = cryptoAllocMem(sizeof(X509CertInfo));
358 
359  //Successful memory allocation?
360  if(certInfo != NULL)
361  {
363 
364  //Additional certificate parsing options
366  options.ignoreUnknownExtensions = TRUE;
367 
368  //Parse X.509 certificate
369  error = x509ParseCertificateEx(derCert, derCertLen, certInfo,
370  &options);
371 
372  //Check status code
373  if(!error)
374  {
375  //Import the EdDSA public key
376  error = x509ImportEddsaPublicKey(publicKey,
377  &certInfo->tbsCert.subjectPublicKeyInfo);
378  }
379 
380  //Release previously allocated memory
381  cryptoFreeMem(certInfo);
382  }
383  else
384  {
385  //Failed to allocate memory
386  error = ERROR_OUT_OF_MEMORY;
387  }
388  }
389 
390  //Release previously allocated memory
391  cryptoFreeMem(derCert);
392  }
393  else
394  {
395  //Failed to allocate memory
396  error = ERROR_OUT_OF_MEMORY;
397  }
398  }
399 
400  //Return status code
401  return error;
402 #else
403  //Not implemented
404  return ERROR_NOT_IMPLEMENTED;
405 #endif
406 }
407 
408 
409 /**
410  * @brief Extract the type of the public key contained in a PEM certificate
411  * @param[in] input Pointer to the PEM certificate
412  * @param[in] length Length of the PEM certificate
413  * @return Public key type
414  **/
415 
417 {
418  error_t error;
419  uint8_t *derCert;
420  size_t derCertLen;
421  X509KeyType keyType;
422  X509CertInfo *certInfo;
423  size_t oidLen;
424  const uint8_t *oid;
425 
426  //Initialize variable
427  keyType = X509_KEY_TYPE_UNKNOWN;
428 
429  //The first pass calculates the length of the DER-encoded certificate
430  error = pemImportCertificate(input, length, NULL, &derCertLen,
431  NULL);
432 
433  //Check status code
434  if(!error)
435  {
436  //Allocate a memory buffer to hold the DER-encoded certificate
437  derCert = cryptoAllocMem(derCertLen);
438 
439  //Successful memory allocation?
440  if(derCert != NULL)
441  {
442  //The second pass decodes the PEM certificate
443  error = pemImportCertificate(input, length, derCert, &derCertLen,
444  NULL);
445 
446  //Check status code
447  if(!error)
448  {
449  //Allocate a memory buffer to store X.509 certificate info
450  certInfo = cryptoAllocMem(sizeof(X509CertInfo));
451 
452  //Successful memory allocation?
453  if(certInfo != NULL)
454  {
456 
457  //Additional certificate parsing options
459  options.ignoreUnknownExtensions = TRUE;
460 
461  //Parse X.509 certificate
462  error = x509ParseCertificateEx(derCert, derCertLen, certInfo,
463  &options);
464 
465  //Check status code
466  if(!error)
467  {
468  //Point to the public key identifier
471 
472  //Get the public key type that matches the specified OID
473  keyType = x509GetPublicKeyType(oid, oidLen);
474  }
475 
476  //Release previously allocated memory
477  cryptoFreeMem(certInfo);
478  }
479  }
480 
481  //Release previously allocated memory
482  cryptoFreeMem(derCert);
483  }
484  }
485 
486  //Return the public key type
487  return keyType;
488 }
489 
490 #endif
X.509 certificate parsing.
error_t x509ImportEcPublicKey(EcPublicKey *publicKey, const X509SubjectPublicKeyInfo *publicKeyInfo)
Import an EC public key.
X509TbsCertificate tbsCert
Definition: x509_common.h:1121
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
X509OctetString oid
Definition: x509_common.h:840
#define TRUE
Definition: os_port.h:50
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
error_t x509ImportDsaPublicKey(DsaPublicKey *publicKey, const X509SubjectPublicKeyInfo *publicKeyInfo)
Import a DSA public key.
uint8_t oid[]
Definition: lldp_tlv.h:300
Certificate parsing options.
Definition: x509_common.h:1334
error_t pemImportDsaCertPublicKey(DsaPublicKey *publicKey, const char_t *input, size_t length)
Extract the DSA public key from a PEM certificate.
error_t pemImportCertificate(const char_t *input, size_t inputLen, uint8_t *output, size_t *outputLen, size_t *consumed)
Decode a PEM file containing a certificate.
Definition: pem_import.c:55
PEM file import functions.
DSA public key.
Definition: dsa.h:61
const X509Options X509_DEFAULT_OPTIONS
Definition: x509_common.c:169
X.509 certificate.
Definition: x509_common.h:1119
error_t
Error codes.
Definition: error.h:43
error_t x509ParseCertificateEx(const uint8_t *data, size_t length, X509CertInfo *certInfo, const X509Options *options)
Parse a X.509 certificate.
EdDSA public key.
Definition: eddsa.h:64
RSA public key.
Definition: rsa.h:57
error_t x509ImportEddsaPublicKey(EddsaPublicKey *publicKey, const X509SubjectPublicKeyInfo *publicKeyInfo)
Import an EdDSA public key.
General definitions for cryptographic algorithms.
uint8_t length
Definition: tcp.h:375
PEM file decryption.
error_t pemImportEddsaCertPublicKey(EddsaPublicKey *publicKey, const char_t *input, size_t length)
Extract the EdDSA public key from a PEM certificate.
EC public key.
Definition: ec.h:421
char char_t
Definition: compiler_port.h:55
error_t x509ImportRsaPublicKey(RsaPublicKey *publicKey, const X509SubjectPublicKeyInfo *publicKeyInfo)
Import an RSA public key.
error_t pemImportRsaCertPublicKey(RsaPublicKey *publicKey, const char_t *input, size_t length)
Extract the RSA public key from a PEM certificate.
#define cryptoFreeMem(p)
Definition: crypto.h:833
PKCS #8 key parsing.
uint8_t oidLen
Definition: lldp_tlv.h:299
#define cryptoAllocMem(size)
Definition: crypto.h:828
uint8_t options[]
Definition: tcp.h:364
const uint8_t * value
Definition: x509_common.h:702
error_t pemImportEcCertPublicKey(EcPublicKey *publicKey, const char_t *input, size_t length)
Extract the EC public key from a PEM certificate.
@ X509_KEY_TYPE_UNKNOWN
Definition: x509_common.h:634
Parsing of ASN.1 encoded keys.
PKCS #5 decryption routines.
X509KeyType
Public Key types.
Definition: x509_common.h:633
X509SubjectPublicKeyInfo subjectPublicKeyInfo
Definition: x509_common.h:1109
X509KeyType x509GetPublicKeyType(const uint8_t *oid, size_t length)
Get the public key type that matches the specified OID.
Definition: x509_common.c:835
Debugging facilities.
PEM certificate public key import functions.
X509KeyType pemGetCertPublicKeyType(const char_t *input, size_t length)
Extract the type of the public key contained in a PEM certificate.