x509_csr_parse.c
Go to the documentation of this file.
1 /**
2  * @file x509_csr_parse.c
3  * @brief CSR (Certificate Signing Request) parsing
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 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.4.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/x509_cert_parse.h"
38 #include "pkix/x509_csr_parse.h"
39 #include "pkix/x509_key_parse.h"
40 #include "pkix/x509_sign_parse.h"
41 #include "encoding/asn1.h"
42 #include "encoding/oid.h"
43 #include "debug.h"
44 
45 //Check crypto library configuration
46 #if (X509_SUPPORT == ENABLED)
47 
48 
49 /**
50  * @brief Parse a CSR (Certificate Signing Request)
51  * @param[in] data Pointer to the CSR to parse
52  * @param[in] length Length of the CSR
53  * @param[out] csrInfo Information resulting from the parsing process
54  * @return Error code
55  **/
56 
57 error_t x509ParseCsr(const uint8_t *data, size_t length,
58  X509CsrInfo *csrInfo)
59 {
60  error_t error;
61  size_t totalLength;
63  Asn1Tag tag;
64 
65  //Debug message
66  TRACE_DEBUG("Parsing X.509 CSR...\r\n");
67 
68  //Check parameters
69  if(data == NULL || csrInfo == NULL)
71 
72  //Clear the CSR information structure
73  osMemset(csrInfo, 0, sizeof(X509CsrInfo));
74 
75  //Point to the CSR attributes
76  attributes = &csrInfo->certReqInfo.attributes;
77  //Where pathLenConstraint does not appear, no limit is imposed
78  attributes->extensionReq.basicConstraints.pathLenConstraint = -1;
79 
80  //The CSR is encapsulated within a sequence
81  error = asn1ReadTag(data, length, &tag);
82  //Failed to decode ASN.1 tag?
83  if(error)
84  return error;
85 
86  //Point to the very first field
87  data = tag.value;
88  length = tag.length;
89 
90  //Parse CertificationRequestInfo structure
92  &csrInfo->certReqInfo);
93  //Any error to report?
94  if(error)
95  return error;
96 
97  //Point to the next field
98  data += totalLength;
100 
101  //Parse SignatureAlgorithm structure
103  &csrInfo->signatureAlgo);
104  //Any error to report?
105  if(error)
106  return error;
107 
108  //Point to the next field
109  data += totalLength;
110  length -= totalLength;
111 
112  //Parse Signature structure
114  &csrInfo->signatureValue);
115  //Any error to report?
116  if(error)
117  return error;
118 
119  //CSR successfully parsed
120  return NO_ERROR;
121 }
122 
123 
124 /**
125  * @brief Parse CertificationRequestInfo structure
126  * @param[in] data Pointer to the ASN.1 structure to parse
127  * @param[in] length Length of the ASN.1 structure
128  * @param[out] totalLength Number of bytes that have been parsed
129  * @param[out] certReqInfo Information resulting from the parsing process
130  * @return Error code
131  **/
132 
134  size_t *totalLength, X509CertRequestInfo *certReqInfo)
135 {
136  error_t error;
137  int32_t version;
138  size_t n;
139  Asn1Tag tag;
140 
141  //Debug message
142  TRACE_DEBUG(" Parsing CertificationRequestInfo...\r\n");
143 
144  //Read the contents of the CertificationRequestInfo structure
145  error = asn1ReadTag(data, length, &tag);
146  //Failed to decode ASN.1 tag?
147  if(error)
148  return error;
149 
150  //Save the total length of the field
151  *totalLength = tag.totalLength;
152 
153  //The ASN.1 DER-encoded CertificationRequestInfo is used as the input
154  //to the signature function
155  certReqInfo->raw.value = data;
156  certReqInfo->raw.length = tag.totalLength;
157 
158  //Point to the very first field of the CertificationRequestInfo
159  data = tag.value;
160  length = tag.length;
161 
162  //Parse Version field
163  error = asn1ReadInt32(data, length, &tag, &version);
164  //Any parsing error?
165  if(error)
166  return error;
167 
168  //Save version number
169  certReqInfo->version = (X509Version) version;
170 
171  //Point to the next field
172  data += tag.totalLength;
173  length -= tag.totalLength;
174 
175  //Parse Subject field
176  error = x509ParseName(data, length, &n, &certReqInfo->subject);
177  //Any parsing error?
178  if(error)
179  return error;
180 
181  //Point to the next field
182  data += n;
183  length -= n;
184 
185  //Parse SubjectPublicKeyInfo field
187  &certReqInfo->subjectPublicKeyInfo);
188  //Any parsing error?
189  if(error)
190  return error;
191 
192  //Point to the next field
193  data += n;
194  length -= n;
195 
196  //Parse Attributes field
197  error = x509ParseAttributes(data, length, &n, &certReqInfo->attributes);
198  //Any parsing error?
199  if(error)
200  return error;
201 
202  //No error to report
203  return NO_ERROR;
204 }
205 
206 
207 /**
208  * @brief Parse CSR attributes
209  * @param[in] data Pointer to the ASN.1 structure to parse
210  * @param[in] length Length of the ASN.1 structure
211  * @param[out] totalLength Number of bytes that have been parsed
212  * @param[out] attributes Information resulting from the parsing process
213  * @return Error code
214  **/
215 
216 error_t x509ParseAttributes(const uint8_t *data, size_t length,
218 {
219  error_t error;
220  size_t n;
221  Asn1Tag tag;
222  X509Attribute attribute;
223 
224  //Debug message
225  TRACE_DEBUG(" Parsing Attributes...\r\n");
226 
227  //Explicit tagging is used to encode the Attributes field
228  error = asn1ReadTag(data, length, &tag);
229  //Failed to decode ASN.1 tag?
230  if(error)
231  return error;
232 
233  //Enforce encoding, class and type
234  error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_CONTEXT_SPECIFIC, 0);
235  //Invalid tag?
236  if(error)
237  return error;
238 
239  //This field is a collection of attributes providing additional information
240  //about the subject of the certificate
241  attributes->raw.value = tag.value;
242  attributes->raw.length = tag.length;
243 
244  //Point to the first item of the collection
245  data = tag.value;
246  length = tag.length;
247 
248  //Loop through the collection of attributes
249  while(length > 0)
250  {
251  //Each item binds an attribute identifier to one or more attribute values
252  error = x509ParseAttribute(data, length, &n, &attribute);
253  //Any error to report?
254  if(error)
255  return error;
256 
257  //PKCS#9 Challenge Password attribute found?
258  if(!oidComp(attribute.oid.value, attribute.oid.length,
260  {
261  //The interpretation of challenge passwords is intended to be specified
262  //by certificate issuers
263  error = x509ParseChallengePassword(attribute.data.value,
264  attribute.data.length, &attributes->challengePwd);
265  }
266  //PKCS#9 Extension Request attribute found?
267  else if(!oidComp(attribute.oid.value, attribute.oid.length,
269  {
270  //This attribute may be used to carry information about certificate
271  //extensions the requester wishes to be included in a certificate
272  error = x509ParseExtensionRequest(attribute.data.value,
273  attribute.data.length, &attributes->extensionReq);
274  }
275  //Unknown attribute?
276  else
277  {
278  //Discard current attribute
279  error = NO_ERROR;
280  }
281 
282  //Any parsing error?
283  if(error)
284  return error;
285 
286  //Next attribute
287  data += n;
288  length -= n;
289  }
290 
291  //Successful processing
292  return NO_ERROR;
293 }
294 
295 
296 /**
297  * @brief Parse CSR attribute
298  * @param[in] data Pointer to the ASN.1 structure to parse
299  * @param[in] length Length of the ASN.1 structure
300  * @param[out] totalLength Number of bytes that have been parsed
301  * @param[out] attribute Information resulting from the parsing process
302  * @return Error code
303  **/
304 
305 error_t x509ParseAttribute(const uint8_t *data, size_t length,
306  size_t *totalLength, X509Attribute *attribute)
307 {
308  error_t error;
309  Asn1Tag tag;
310 
311  //The attribute is encapsulated within a sequence
312  error = asn1ReadSequence(data, length, &tag);
313  //Failed to decode ASN.1 tag?
314  if(error)
315  return error;
316 
317  //Save the total length of the attribute
318  *totalLength = tag.totalLength;
319 
320  //Each item binds an attribute identifier to one or more attribute values
321  data = tag.value;
322  length = tag.length;
323 
324  //Read attribute identifier
325  error = asn1ReadOid(data, length, &tag);
326  //Failed to decode ASN.1 tag?
327  if(error)
328  return error;
329 
330  //Save the object identifier
331  attribute->oid.value = tag.value;
332  attribute->oid.length = tag.length;
333 
334  //Next item
335  data += tag.totalLength;
336  length -= tag.totalLength;
337 
338  //Attribute values are encapsulated within a set
339  error = asn1ReadTag(data, length, &tag);
340  //Failed to decode ASN.1 tag?
341  if(error)
342  return error;
343 
344  //Enforce encoding, class and type
346  //Invalid tag?
347  if(error)
348  return error;
349 
350  //Save the value of the attribute
351  attribute->data.value = tag.value;
352  attribute->data.length = tag.length;
353 
354  //Successful processing
355  return NO_ERROR;
356 }
357 
358 
359 /**
360  * @brief Parse ChallengePassword attribute
361  * @param[in] data Pointer to the ASN.1 structure to parse
362  * @param[in] length Length of the ASN.1 structure
363  * @param[out] challengePwd Information resulting from the parsing process
364  * @return Error code
365  **/
366 
368  X509ChallengePassword *challengePwd)
369 {
370  error_t error;
371  Asn1Tag tag;
372 
373  //Debug message
374  TRACE_DEBUG(" Parsing ChallengePassword...\r\n");
375 
376  //Read attribute value
377  error = asn1ReadTag(data, length, &tag);
378  //Failed to decode ASN.1 tag?
379  if(error)
380  return error;
381 
382  //Save challenge password
383  challengePwd->value = (char_t *) tag.value;
384  challengePwd->length = tag.length;
385 
386  //Successful processing
387  return NO_ERROR;
388 }
389 
390 
391 /**
392  * @brief Parse ExtensionRequest attribute
393  * @param[in] data Pointer to the ASN.1 structure to parse
394  * @param[in] length Length of the ASN.1 structure
395  * @param[out] extensionReq Information resulting from the parsing process
396  * @return Error code
397  **/
398 
400  X509Extensions *extensionReq)
401 {
402  error_t error;
403  size_t n;
404  Asn1Tag tag;
405  X509Extension extension;
406 
407  //Debug message
408  TRACE_DEBUG(" Parsing ExtensionRequest...\r\n");
409 
410  //This field is a sequence of one or more certificate extensions
411  error = asn1ReadSequence(data, length, &tag);
412  //Failed to decode ASN.1 tag?
413  if(error)
414  return error;
415 
416  //Raw contents of the ASN.1 sequence
417  extensionReq->raw.value = tag.value;
418  extensionReq->raw.length = tag.length;
419 
420  //Point to the first item of the sequence
421  data = tag.value;
422  length = tag.length;
423 
424  //Loop through the extensions
425  while(length > 0)
426  {
427  //Each extension includes an OID and a value
428  error = x509ParseExtension(data, length, &n, &extension);
429  //Any error to report?
430  if(error)
431  return error;
432 
433  //Jump to the next extension
434  data += n;
435  length -= n;
436 
437  //Test if the current extension is a duplicate
438  error = x509CheckDuplicateExtension(extension.oid.value,
439  extension.oid.length, data, length);
440  //Duplicate extension found?
441  if(error)
442  return error;
443 
444  //Check extension identifier
445  if(!oidComp(extension.oid.value, extension.oid.length,
447  {
448  //Parse BasicConstraints extension
449  error = x509ParseBasicConstraints(extension.critical, extension.data.value,
450  extension.data.length, &extensionReq->basicConstraints);
451  }
452  else if(!oidComp(extension.oid.value, extension.oid.length,
454  {
455  //Parse NameConstraints extension
456  error = x509ParseNameConstraints(extension.critical, extension.data.value,
457  extension.data.length, &extensionReq->nameConstraints);
458  }
459  else if(!oidComp(extension.oid.value, extension.oid.length,
461  {
462  //Parse KeyUsage extension
463  error = x509ParseKeyUsage(extension.critical, extension.data.value,
464  extension.data.length, &extensionReq->keyUsage);
465  }
466  else if(!oidComp(extension.oid.value, extension.oid.length,
468  {
469  //Parse ExtendedKeyUsage extension
470  error = x509ParseExtendedKeyUsage(extension.critical, extension.data.value,
471  extension.data.length, &extensionReq->extKeyUsage);
472  }
473  else if(!oidComp(extension.oid.value, extension.oid.length,
475  {
476  //Parse SubjectAltName extension
477  error = x509ParseSubjectAltName(extension.critical, extension.data.value,
478  extension.data.length, &extensionReq->subjectAltName);
479  }
480  else if(!oidComp(extension.oid.value, extension.oid.length,
482  {
483  //Parse SubjectKeyIdentifier extension
484  error = x509ParseSubjectKeyId(extension.critical, extension.data.value,
485  extension.data.length, &extensionReq->subjectKeyId);
486  }
487  else if(!oidComp(extension.oid.value, extension.oid.length,
489  {
490  //Parse AuthorityKeyIdentifier extension
491  error = x509ParseAuthKeyId(extension.critical, extension.data.value,
492  extension.data.length, &extensionReq->authKeyId);
493  }
494  else if(!oidComp(extension.oid.value, extension.oid.length,
496  {
497  //Parse NetscapeCertType extension
498  error = x509ParseNsCertType(extension.critical, extension.data.value,
499  extension.data.length, &extensionReq->nsCertType);
500  }
501  else
502  {
503  //Discard unknown extensions
504  error = NO_ERROR;
505  }
506 
507  //Any parsing error?
508  if(error)
509  return error;
510  }
511 
512  //Successful processing
513  return NO_ERROR;
514 }
515 
516 #endif
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
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
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:653
error_t asn1ReadOid(const uint8_t *data, size_t length, Asn1Tag *tag)
Read an object identifier from the input stream.
Definition: asn1.c:218
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
ASN.1 (Abstract Syntax Notation One)
@ ASN1_TYPE_SET
Definition: asn1.h:81
#define ASN1_CLASS_UNIVERSAL
Definition: asn1.h:52
#define ASN1_CLASS_CONTEXT_SPECIFIC
Definition: asn1.h:54
uint8_t version
Definition: coap_common.h:177
char char_t
Definition: compiler_port.h:48
General definitions for cryptographic algorithms.
Debugging facilities.
#define TRACE_DEBUG(...)
Definition: debug.h:107
uint8_t n
error_t
Error codes.
Definition: error.h:43
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
uint8_t data[]
Definition: ethernet.h:222
uint16_t totalLength
Definition: ipv4.h:292
int_t oidComp(const uint8_t *oid1, size_t oidLen1, const uint8_t *oid2, size_t oidLen2)
Compare object identifiers.
Definition: oid.c:103
OID (Object Identifier)
#define osMemset(p, value, length)
Definition: os_port.h:135
#define TRUE
Definition: os_port.h:50
uint8_t attributes[]
Definition: radius.h:88
ASN.1 tag.
Definition: asn1.h:102
size_t totalLength
Definition: asn1.h:108
const uint8_t * value
Definition: asn1.h:107
size_t length
Definition: asn1.h:106
CSR attribute.
Definition: x509_common.h:1229
X509OctetString data
Definition: x509_common.h:1231
X509OctetString oid
Definition: x509_common.h:1230
CSR attributes.
Definition: x509_common.h:1240
CertificationRequestInfo structure.
Definition: x509_common.h:1252
X509Version version
Definition: x509_common.h:1254
X509OctetString raw
Definition: x509_common.h:1253
X509Attributes attributes
Definition: x509_common.h:1257
X509SubjectPublicKeyInfo subjectPublicKeyInfo
Definition: x509_common.h:1256
PKCS #9 ChallengePassword attribute.
Definition: x509_common.h:1218
const char_t * value
Definition: x509_common.h:1219
CSR (Certificate Signing Request)
Definition: x509_common.h:1266
X509CertRequestInfo certReqInfo
Definition: x509_common.h:1267
X509OctetString signatureValue
Definition: x509_common.h:1269
X509SignAlgoId signatureAlgo
Definition: x509_common.h:1268
X.509 certificate extension.
Definition: x509_common.h:984
X509OctetString data
Definition: x509_common.h:987
bool_t critical
Definition: x509_common.h:986
X509OctetString oid
Definition: x509_common.h:985
X.509 certificate extensions.
Definition: x509_common.h:996
X509KeyUsage keyUsage
Definition: x509_common.h:1000
X509NsCertType nsCertType
Definition: x509_common.h:1008
X509SubjectKeyId subjectKeyId
Definition: x509_common.h:1003
X509OctetString raw
Definition: x509_common.h:997
X509BasicConstraints basicConstraints
Definition: x509_common.h:998
X509ExtendedKeyUsage extKeyUsage
Definition: x509_common.h:1001
X509SubjectAltName subjectAltName
Definition: x509_common.h:1002
X509NameConstraints nameConstraints
Definition: x509_common.h:999
X509AuthKeyId authKeyId
Definition: x509_common.h:1004
const uint8_t * value
Definition: x509_common.h:647
uint8_t length
Definition: tcp.h:368
error_t x509ParseSubjectAltName(bool_t critical, const uint8_t *data, size_t length, X509SubjectAltName *subjectAltName)
Parse SubjectAltName extension.
error_t x509ParseAuthKeyId(bool_t critical, const uint8_t *data, size_t length, X509AuthKeyId *authKeyId)
Parse AuthorityKeyIdentifier extension.
error_t x509ParseKeyUsage(bool_t critical, const uint8_t *data, size_t length, X509KeyUsage *keyUsage)
Parse KeyUsage extension.
error_t x509ParseNameConstraints(bool_t critical, const uint8_t *data, size_t length, X509NameConstraints *nameConstraints)
Parse NameConstraints extension.
error_t x509ParseExtendedKeyUsage(bool_t critical, const uint8_t *data, size_t length, X509ExtendedKeyUsage *extKeyUsage)
Parse ExtendedKeyUsage extension.
error_t x509ParseNsCertType(bool_t critical, const uint8_t *data, size_t length, X509NsCertType *nsCertType)
Parse NetscapeCertType extension.
error_t x509ParseExtension(const uint8_t *data, size_t length, size_t *totalLength, X509Extension *extension)
Parse X.509 certificate extension.
error_t x509ParseSubjectKeyId(bool_t critical, const uint8_t *data, size_t length, X509SubjectKeyId *subjectKeyId)
Parse SubjectKeyIdentifier extension.
error_t x509ParseBasicConstraints(bool_t critical, const uint8_t *data, size_t length, X509BasicConstraints *basicConstraints)
Parse BasicConstraints extension.
error_t x509CheckDuplicateExtension(const uint8_t *oid, size_t oidLen, const uint8_t *data, size_t length)
Check whether the specified extension is a duplicate.
X.509 extension parsing.
error_t x509ParseName(const uint8_t *data, size_t length, size_t *totalLength, X509Name *name)
Parse Name structure.
X.509 certificate parsing.
const uint8_t X509_SUBJECT_KEY_ID_OID[3]
Definition: x509_common.c:81
const uint8_t X509_NAME_CONSTRAINTS_OID[3]
Definition: x509_common.c:103
const uint8_t X509_NS_CERT_TYPE_OID[9]
Definition: x509_common.c:125
const uint8_t X509_BASIC_CONSTRAINTS_OID[3]
Definition: x509_common.c:89
const uint8_t X509_SUBJECT_ALT_NAME_OID[3]
Definition: x509_common.c:85
const uint8_t X509_EXTENSION_REQUEST_OID[9]
Definition: x509_common.c:166
const uint8_t X509_EXTENDED_KEY_USAGE_OID[3]
Definition: x509_common.c:115
const uint8_t X509_KEY_USAGE_OID[3]
Definition: x509_common.c:83
const uint8_t X509_CHALLENGE_PASSWORD_OID[9]
Definition: x509_common.c:164
const uint8_t X509_AUTHORITY_KEY_ID_OID[3]
Definition: x509_common.c:111
X509Version
X.509 versions.
Definition: x509_common.h:458
error_t x509ParseExtensionRequest(const uint8_t *data, size_t length, X509Extensions *extensionReq)
Parse ExtensionRequest attribute.
error_t x509ParseAttribute(const uint8_t *data, size_t length, size_t *totalLength, X509Attribute *attribute)
Parse CSR attribute.
error_t x509ParseCsr(const uint8_t *data, size_t length, X509CsrInfo *csrInfo)
Parse a CSR (Certificate Signing Request)
error_t x509ParseCertRequestInfo(const uint8_t *data, size_t length, size_t *totalLength, X509CertRequestInfo *certReqInfo)
Parse CertificationRequestInfo structure.
error_t x509ParseChallengePassword(const uint8_t *data, size_t length, X509ChallengePassword *challengePwd)
Parse ChallengePassword attribute.
error_t x509ParseAttributes(const uint8_t *data, size_t length, size_t *totalLength, X509Attributes *attributes)
Parse CSR attributes.
CSR (Certificate Signing Request) parsing.
error_t x509ParseSubjectPublicKeyInfo(const uint8_t *data, size_t length, size_t *totalLength, X509SubjectPublicKeyInfo *publicKeyInfo)
Parse SubjectPublicKeyInfo structure.
Parsing of ASN.1 encoded keys.
error_t x509ParseSignatureValue(const uint8_t *data, size_t length, size_t *totalLength, X509OctetString *signature)
Parse SignatureValue field.
error_t x509ParseSignatureAlgo(const uint8_t *data, size_t length, size_t *totalLength, X509SignAlgoId *signatureAlgo)
Parse SignatureAlgorithm structure.