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.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/crypto.h"
36 #include "pkix/pem_import.h"
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  {
92  //Parse X.509 certificate
93  error = x509ParseCertificateEx(derCert, derCertLen, certInfo,
94  TRUE);
95 
96  //Check status code
97  if(!error)
98  {
99  //Import the RSA public key
100  error = x509ImportRsaPublicKey(publicKey,
101  &certInfo->tbsCert.subjectPublicKeyInfo);
102  }
103 
104  //Release previously allocated memory
105  cryptoFreeMem(certInfo);
106  }
107  else
108  {
109  //Failed to allocate memory
110  error = ERROR_OUT_OF_MEMORY;
111  }
112  }
113 
114  //Release previously allocated memory
115  cryptoFreeMem(derCert);
116  }
117  else
118  {
119  //Failed to allocate memory
120  error = ERROR_OUT_OF_MEMORY;
121  }
122  }
123 
124  //Return status code
125  return error;
126 #else
127  //Not implemented
128  return ERROR_NOT_IMPLEMENTED;
129 #endif
130 }
131 
132 
133 /**
134  * @brief Extract the DSA public key from a PEM certificate
135  * @param[out] publicKey DSA public key resulting from the parsing process
136  * @param[in] input Pointer to the PEM certificate
137  * @param[in] length Length of the PEM certificate
138  * @return Error code
139  **/
140 
142  size_t length)
143 {
144 #if (DSA_SUPPORT == ENABLED)
145  error_t error;
146  uint8_t *derCert;
147  size_t derCertLen;
148  X509CertInfo *certInfo;
149 
150  //The first pass calculates the length of the DER-encoded certificate
151  error = pemImportCertificate(input, length, NULL, &derCertLen,
152  NULL);
153 
154  //Check status code
155  if(!error)
156  {
157  //Allocate a memory buffer to hold the DER-encoded certificate
158  derCert = cryptoAllocMem(derCertLen);
159 
160  //Successful memory allocation?
161  if(derCert != NULL)
162  {
163  //The second pass decodes the PEM certificate
164  error = pemImportCertificate(input, length, derCert, &derCertLen,
165  NULL);
166 
167  //Check status code
168  if(!error)
169  {
170  //Allocate a memory buffer to store X.509 certificate info
171  certInfo = cryptoAllocMem(sizeof(X509CertInfo));
172 
173  //Successful memory allocation?
174  if(certInfo != NULL)
175  {
176  //Parse X.509 certificate
177  error = x509ParseCertificateEx(derCert, derCertLen, certInfo,
178  TRUE);
179 
180  //Check status code
181  if(!error)
182  {
183  //Import the DSA public key
184  error = x509ImportDsaPublicKey(publicKey,
185  &certInfo->tbsCert.subjectPublicKeyInfo);
186  }
187 
188  //Release previously allocated memory
189  cryptoFreeMem(certInfo);
190  }
191  else
192  {
193  //Failed to allocate memory
194  error = ERROR_OUT_OF_MEMORY;
195  }
196  }
197 
198  //Release previously allocated memory
199  cryptoFreeMem(derCert);
200  }
201  else
202  {
203  //Failed to allocate memory
204  error = ERROR_OUT_OF_MEMORY;
205  }
206  }
207 
208  //Return status code
209  return error;
210 #else
211  //Not implemented
212  return ERROR_NOT_IMPLEMENTED;
213 #endif
214 }
215 
216 
217 /**
218  * @brief Extract the EC public key from a PEM certificate
219  * @param[out] publicKey EC public key resulting from the parsing process
220  * @param[in] input Pointer to the PEM certificate
221  * @param[in] length Length of the PEM certificate
222  * @return Error code
223  **/
224 
226  size_t length)
227 {
228 #if (EC_SUPPORT == ENABLED)
229  error_t error;
230  uint8_t *derCert;
231  size_t derCertLen;
232  X509CertInfo *certInfo;
233 
234  //The first pass calculates the length of the DER-encoded certificate
235  error = pemImportCertificate(input, length, NULL, &derCertLen,
236  NULL);
237 
238  //Check status code
239  if(!error)
240  {
241  //Allocate a memory buffer to hold the DER-encoded certificate
242  derCert = cryptoAllocMem(derCertLen);
243 
244  //Successful memory allocation?
245  if(derCert != NULL)
246  {
247  //The second pass decodes the PEM certificate
248  error = pemImportCertificate(input, length, derCert, &derCertLen,
249  NULL);
250 
251  //Check status code
252  if(!error)
253  {
254  //Allocate a memory buffer to store X.509 certificate info
255  certInfo = cryptoAllocMem(sizeof(X509CertInfo));
256 
257  //Successful memory allocation?
258  if(certInfo != NULL)
259  {
260  //Parse X.509 certificate
261  error = x509ParseCertificateEx(derCert, derCertLen, certInfo,
262  TRUE);
263 
264  //Check status code
265  if(!error)
266  {
267  //Import the EC public key
268  error = x509ImportEcPublicKey(publicKey,
269  &certInfo->tbsCert.subjectPublicKeyInfo);
270  }
271 
272  //Release previously allocated memory
273  cryptoFreeMem(certInfo);
274  }
275  else
276  {
277  //Failed to allocate memory
278  error = ERROR_OUT_OF_MEMORY;
279  }
280  }
281 
282  //Release previously allocated memory
283  cryptoFreeMem(derCert);
284  }
285  else
286  {
287  //Failed to allocate memory
288  error = ERROR_OUT_OF_MEMORY;
289  }
290  }
291 
292  //Return status code
293  return error;
294 #else
295  //Not implemented
296  return ERROR_NOT_IMPLEMENTED;
297 #endif
298 }
299 
300 
301 /**
302  * @brief Extract the EdDSA public key from a PEM certificate
303  * @param[out] publicKey EdDSA public key resulting from the parsing process
304  * @param[in] input Pointer to the PEM certificate
305  * @param[in] length Length of the PEM certificate
306  * @return Error code
307  **/
308 
310  const char_t *input, size_t length)
311 {
312 #if (ED25519_SUPPORT == ENABLED || ED448_SUPPORT == ENABLED)
313  error_t error;
314  uint8_t *derCert;
315  size_t derCertLen;
316  X509CertInfo *certInfo;
317 
318  //The first pass calculates the length of the DER-encoded certificate
319  error = pemImportCertificate(input, length, NULL, &derCertLen,
320  NULL);
321 
322  //Check status code
323  if(!error)
324  {
325  //Allocate a memory buffer to hold the DER-encoded certificate
326  derCert = cryptoAllocMem(derCertLen);
327 
328  //Successful memory allocation?
329  if(derCert != NULL)
330  {
331  //The second pass decodes the PEM certificate
332  error = pemImportCertificate(input, length, derCert, &derCertLen,
333  NULL);
334 
335  //Check status code
336  if(!error)
337  {
338  //Allocate a memory buffer to store X.509 certificate info
339  certInfo = cryptoAllocMem(sizeof(X509CertInfo));
340 
341  //Successful memory allocation?
342  if(certInfo != NULL)
343  {
344  //Parse X.509 certificate
345  error = x509ParseCertificateEx(derCert, derCertLen, certInfo,
346  TRUE);
347 
348  //Check status code
349  if(!error)
350  {
351  //Import the EdDSA public key
352  error = x509ImportEddsaPublicKey(publicKey,
353  &certInfo->tbsCert.subjectPublicKeyInfo);
354  }
355 
356  //Release previously allocated memory
357  cryptoFreeMem(certInfo);
358  }
359  else
360  {
361  //Failed to allocate memory
362  error = ERROR_OUT_OF_MEMORY;
363  }
364  }
365 
366  //Release previously allocated memory
367  cryptoFreeMem(derCert);
368  }
369  else
370  {
371  //Failed to allocate memory
372  error = ERROR_OUT_OF_MEMORY;
373  }
374  }
375 
376  //Return status code
377  return error;
378 #else
379  //Not implemented
380  return ERROR_NOT_IMPLEMENTED;
381 #endif
382 }
383 
384 
385 /**
386  * @brief Extract the type of the public key contained in a PEM certificate
387  * @param[in] input Pointer to the PEM certificate
388  * @param[in] length Length of the PEM certificate
389  * @return Public key type
390  **/
391 
393 {
394  error_t error;
395  uint8_t *derCert;
396  size_t derCertLen;
397  X509KeyType keyType;
398  X509CertInfo *certInfo;
399  size_t oidLen;
400  const uint8_t *oid;
401 
402  //Initialize variable
403  keyType = X509_KEY_TYPE_UNKNOWN;
404 
405  //The first pass calculates the length of the DER-encoded certificate
406  error = pemImportCertificate(input, length, NULL, &derCertLen,
407  NULL);
408 
409  //Check status code
410  if(!error)
411  {
412  //Allocate a memory buffer to hold the DER-encoded certificate
413  derCert = cryptoAllocMem(derCertLen);
414 
415  //Successful memory allocation?
416  if(derCert != NULL)
417  {
418  //The second pass decodes the PEM certificate
419  error = pemImportCertificate(input, length, derCert, &derCertLen,
420  NULL);
421 
422  //Check status code
423  if(!error)
424  {
425  //Allocate a memory buffer to store X.509 certificate info
426  certInfo = cryptoAllocMem(sizeof(X509CertInfo));
427 
428  //Successful memory allocation?
429  if(certInfo != NULL)
430  {
431  //Parse X.509 certificate
432  error = x509ParseCertificateEx(derCert, derCertLen, certInfo,
433  TRUE);
434 
435  //Check status code
436  if(!error)
437  {
438  //Point to the public key identifier
441 
442  //Get the public key type that matches the specified OID
443  keyType = x509GetPublicKeyType(oid, oidLen);
444  }
445 
446  //Release previously allocated memory
447  cryptoFreeMem(certInfo);
448  }
449  }
450 
451  //Release previously allocated memory
452  cryptoFreeMem(derCert);
453  }
454  }
455 
456  //Return the public key type
457  return keyType;
458 }
459 
460 #endif
X.509 certificate parsing.
error_t x509ImportEcPublicKey(EcPublicKey *publicKey, const X509SubjectPublicKeyInfo *publicKeyInfo)
Import an EC public key.
X509TbsCertificate tbsCert
Definition: x509_common.h:1120
@ 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
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:61
PEM file import functions.
DSA public key.
Definition: dsa.h:61
X.509 certificate.
Definition: x509_common.h:1119
error_t
Error codes.
Definition: error.h:43
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:826
PKCS #8 key parsing.
uint8_t oidLen
Definition: lldp_tlv.h:299
error_t x509ParseCertificateEx(const uint8_t *data, size_t length, X509CertInfo *certInfo, bool_t ignoreUnknown)
Parse a X.509 certificate.
#define cryptoAllocMem(size)
Definition: crypto.h:821
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:804
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.