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