x509_cert_ext_format.c
Go to the documentation of this file.
1 /**
2  * @file x509_cert_ext_format.c
3  * @brief X.509 extension formatting
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_format.h"
38 #include "encoding/asn1.h"
39 #include "debug.h"
40 
41 //Check crypto library configuration
42 #if (X509_SUPPORT == ENABLED)
43 
44 
45 /**
46  * @brief Format Extensions structure
47  * @param[in] extensions Pointer to the X.509 extensions
48  * @param[in] subjectKeyId SubjectKeyIdentifier extension
49  * @param[in] authKeyId AuthorityKeyIdentifier extension
50  * @param[out] output Buffer where to format the ASN.1 structure
51  * @param[out] written Length of the resulting ASN.1 structure
52  * @return Error code
53  **/
54 
56  const X509SubjectKeyId *subjectKeyId, const X509AuthKeyId *authKeyId,
57  uint8_t *output, size_t *written)
58 {
59  error_t error;
60  uint_t i;
61  size_t n;
62  size_t length;
63  uint8_t *p;
64  Asn1Tag tag;
65 
66  //Point to the buffer where to write the ASN.1 structure
67  p = output;
68  //Length of the ASN.1 structure
69  length = 0;
70 
71  //Format NetscapeCertType extension
72  error = x509FormatNsCertType(&extensions->nsCertType, p, &n);
73  //Any error to report?
74  if(error)
75  return error;
76 
77  //Advance data pointer
78  p += n;
79  length += n;
80 
81  //Format BasicConstraints extension
82  error = x509FormatBasicConstraints(&extensions->basicConstraints, p, &n);
83  //Any error to report?
84  if(error)
85  return error;
86 
87  //Advance data pointer
88  p += n;
89  length += n;
90 
91  //Format KeyUsage extension
92  error = x509FormatKeyUsage(&extensions->keyUsage, p, &n);
93  //Any error to report?
94  if(error)
95  return error;
96 
97  //Advance data pointer
98  p += n;
99  length += n;
100 
101  //Format SubjectKeyId extension
102  error = x509FormatSubjectKeyId(subjectKeyId, p, &n);
103  //Any error to report?
104  if(error)
105  return error;
106 
107  //Advance data pointer
108  p += n;
109  length += n;
110 
111  //Format AuthorityKeyId extension
112  error = x509FormatAuthorityKeyId(authKeyId, p, &n);
113  //Any error to report?
114  if(error)
115  return error;
116 
117  //Advance data pointer
118  p += n;
119  length += n;
120 
121  //Format SubjectAltName extension
122  error = x509FormatSubjectAltName(&extensions->subjectAltName, p, &n);
123  //Any error to report?
124  if(error)
125  return error;
126 
127  //Advance data pointer
128  p += n;
129  length += n;
130 
131  //Add custom extensions, if any
132  for(i = 0; i < extensions->numCustomExtensions; i++)
133  {
134  //Format current extension
135  error = x509FormatExtension(&extensions->customExtensions[i], p, &n);
136  //Any error to report?
137  if(error)
138  return error;
139 
140  //Advance data pointer
141  p += n;
142  length += n;
143  }
144 
145  //Any extensions written?
146  if(length > 0)
147  {
148  //The extensions are encapsulated within a sequence
149  tag.constructed = TRUE;
152  tag.length = length;
153  tag.value = output;
154 
155  //Write the corresponding ASN.1 tag
156  error = asn1WriteTag(&tag, FALSE, output, &n);
157  //Any error to report?
158  if(error)
159  return error;
160 
161  //Explicit tagging shall be used to encode the Extensions structure
162  tag.constructed = TRUE;
164  tag.objType = 3;
165  tag.length = n;
166  tag.value = output;
167 
168  //Write the corresponding ASN.1 tag
169  error = asn1WriteTag(&tag, FALSE, output, &length);
170  //Any error to report?
171  if(error)
172  return error;
173  }
174 
175  //Total number of bytes that have been written
176  *written = length;
177 
178  //Successful processing
179  return NO_ERROR;
180 }
181 
182 
183 /**
184  * @brief Format X.509 certificate extension
185  * @param[in] extension Pointer to the extension
186  * @param[out] output Buffer where to format the ASN.1 structure
187  * @param[out] written Length of the resulting ASN.1 structure
188  * @return Error code
189  **/
190 
191 error_t x509FormatExtension(const X509Extension *extension, uint8_t *output,
192  size_t *written)
193 {
194  error_t error;
195  size_t n;
196  size_t length;
197  uint8_t value;
198  uint8_t *p;
199  Asn1Tag tag;
200 
201  //Point to the buffer where to write the ASN.1 structure
202  p = output;
203  //Length of the ASN.1 structure
204  length = 0;
205 
206  //Format the extension identifier
207  tag.constructed = FALSE;
210  tag.length = extension->oid.length;
211  tag.value = extension->oid.value;
212 
213  //Write the corresponding ASN.1 tag
214  error = asn1WriteTag(&tag, FALSE, p, &n);
215  //Any error to report?
216  if(error)
217  return error;
218 
219  //Advance data pointer
220  p += n;
221  length += n;
222 
223  //An extension includes the critical flag, with a default value of FALSE
224  if(extension->critical)
225  {
226  //Mark the extension as critical
227  value = 0xFF;
228 
229  //Format the critical field
230  tag.constructed = FALSE;
233  tag.length = 1;
234  tag.value = &value;
235 
236  //Write the corresponding ASN.1 tag
237  error = asn1WriteTag(&tag, FALSE, p, &n);
238  //Any error to report?
239  if(error)
240  return error;
241 
242  //Advance data pointer
243  p += n;
244  length += n;
245  }
246 
247  //The extension value is encapsulated in an octet string
248  tag.constructed = FALSE;
251  tag.length = extension->data.length;
252  tag.value = extension->data.value;
253 
254  //Write the corresponding ASN.1 tag
255  error = asn1WriteTag(&tag, FALSE, p, &n);
256  //Any error to report?
257  if(error)
258  return error;
259 
260  //Adjust the length of the extension
261  length += n;
262 
263  //The extension is encapsulated within a sequence
264  tag.constructed = TRUE;
267  tag.length = length;
268  tag.value = output;
269 
270  //Write the corresponding ASN.1 tag
271  error = asn1WriteTag(&tag, FALSE, output, &length);
272  //Any error to report?
273  if(error)
274  return error;
275 
276  //Total number of bytes that have been written
277  *written = length;
278 
279  //Successful processing
280  return NO_ERROR;
281 }
282 
283 
284 /**
285  * @brief Format BasicConstraints extension
286  * @param[in] basicConstraints Value of the extension
287  * @param[out] output Buffer where to format the ASN.1 structure
288  * @param[out] written Length of the resulting ASN.1 structure
289  * @return Error code
290  **/
291 
293  uint8_t *output, size_t *written)
294 {
295  error_t error;
296  uint32_t value;
297  size_t n;
298  size_t length;
299  uint8_t *p;
300  Asn1Tag tag;
301  uint8_t buffer[3];
302 
303  //Point to the buffer where to write the ASN.1 structure
304  p = output;
305  //Length of the ASN.1 structure
306  length = 0;
307 
308  //The basic constraints extension identifies whether the subject of the
309  //certificate is a CA and the maximum depth of valid certification paths
310  //that include this certificate
311  if(basicConstraints->cA || basicConstraints->critical)
312  {
313  //Format the extension identifier
314  tag.constructed = FALSE;
317  tag.length = sizeof(X509_BASIC_CONSTRAINTS_OID);
319 
320  //Write the corresponding ASN.1 tag
321  error = asn1WriteTag(&tag, FALSE, p, &n);
322  //Any error to report?
323  if(error)
324  return error;
325 
326  //Advance data pointer
327  p += n;
328  length += n;
329 
330  //An extension includes the critical flag, with a default value of FALSE
331  if(basicConstraints->critical)
332  {
333  //Mark the extension as critical
334  buffer[0] = 0xFF;
335 
336  //Format the critical field
337  tag.constructed = FALSE;
340  tag.length = 1;
341  tag.value = buffer;
342 
343  //Write the corresponding ASN.1 tag
344  error = asn1WriteTag(&tag, FALSE, p, &n);
345  //Any error to report?
346  if(error)
347  return error;
348 
349  //Advance data pointer
350  p += n;
351  length += n;
352  }
353 
354  //Total number of bytes that have been written
355  *written = length;
356 
357  //Length of the extension value
358  length = 0;
359 
360  //Check whether the cA boolean is set
361  if(basicConstraints->cA)
362  {
363  //The cA boolean indicates whether the certified public key may be used
364  //to verify certificate signatures
365  buffer[0] = 0xFF;
366 
367  //Format the cA field
368  tag.constructed = FALSE;
371  tag.length = 1;
372  tag.value = buffer;
373 
374  //Write the corresponding ASN.1 tag
375  error = asn1WriteTag(&tag, FALSE, p, &length);
376  //Any error to report?
377  if(error)
378  return error;
379 
380  //Where pathLenConstraint does not appear, no limit is imposed
381  if(basicConstraints->pathLenConstraint >= 0)
382  {
383  //The pathLenConstraint field gives the maximum number of non-self-issued
384  //intermediate certificates that may follow this certificate in a valid
385  //certification path
386  value = basicConstraints->pathLenConstraint;
387 
388  //Encode pathLenConstraint value
389  error = asn1WriteInt32(value, FALSE, p + length, &n);
390  //Any error to report?
391  if(error)
392  return error;
393 
394  //Update the length of the extension value
395  length += n;
396  }
397  }
398 
399  //The BasicConstraints extension is encapsulated within a sequence
400  tag.constructed = TRUE;
403  tag.length = length;
404  tag.value = p;
405 
406  //Write the corresponding ASN.1 tag
407  error = asn1WriteTag(&tag, FALSE, p, &n);
408  //Any error to report?
409  if(error)
410  return error;
411 
412  //The extension value is encapsulated in an octet string
413  tag.constructed = FALSE;
416  tag.length = n;
417  tag.value = p;
418 
419  //Write the corresponding ASN.1 tag
420  error = asn1WriteTag(&tag, FALSE, output + *written, &n);
421  //Any error to report?
422  if(error)
423  return error;
424 
425  //Adjust the length of the extension
426  *written += n;
427 
428  //The extension is encapsulated within a sequence
429  tag.constructed = TRUE;
432  tag.length = *written;
433  tag.value = output;
434 
435  //Write the corresponding ASN.1 tag
436  error = asn1WriteTag(&tag, FALSE, output, &length);
437  //Any error to report?
438  if(error)
439  return error;
440  }
441 
442  //Total number of bytes that have been written
443  *written = length;
444 
445  //Successful processing
446  return NO_ERROR;
447 }
448 
449 
450 /**
451  * @brief Format KeyUsage extension
452  * @param[in] keyUsage Value of the extension
453  * @param[out] output Buffer where to format the ASN.1 structure
454  * @param[out] written Length of the resulting ASN.1 structure
455  * @return Error code
456  **/
457 
458 error_t x509FormatKeyUsage(const X509KeyUsage *keyUsage, uint8_t *output,
459  size_t *written)
460 {
461  error_t error;
462  uint_t k;
463  size_t n;
464  size_t length;
465  uint8_t *p;
466  Asn1Tag tag;
467  uint8_t buffer[3];
468 
469  //Initialize status code
470  error = NO_ERROR;
471 
472  //Point to the buffer where to write the ASN.1 structure
473  p = output;
474  //Length of the ASN.1 structure
475  length = 0;
476 
477  //The key usage extension defines the purpose of the key contained in the
478  //certificate
479  if(keyUsage->bitmap != 0 || keyUsage->critical)
480  {
481  //Format the extension identifier
482  tag.constructed = FALSE;
485  tag.length = sizeof(X509_KEY_USAGE_OID);
487 
488  //Write the corresponding ASN.1 tag
489  error = asn1WriteTag(&tag, FALSE, p, &n);
490  //Any error to report?
491  if(error)
492  return error;
493 
494  //Advance data pointer
495  p += n;
496  length += n;
497 
498  //An extension includes the critical flag, with a default value of FALSE
499  if(keyUsage->critical)
500  {
501  //Mark the extension as critical
502  buffer[0] = 0xFF;
503 
504  //Format the critical field
505  tag.constructed = FALSE;
508  tag.length = 1;
509  tag.value = buffer;
510 
511  //Write the corresponding ASN.1 tag
512  error = asn1WriteTag(&tag, FALSE, p, &n);
513  //Any error to report?
514  if(error)
515  return error;
516 
517  //Advance data pointer
518  p += n;
519  length += n;
520  }
521 
522  //Calculate the length, in bits, of the KeyUsage value
523  for(k = 16; k > 0; k--)
524  {
525  if(keyUsage->bitmap & (1U << (k - 1)))
526  break;
527  }
528 
529  //Total number of bytes needed to encode the KeyUsage value
530  n = 0;
531 
532  //Encode bit string value
533  if(k <= 8)
534  {
535  buffer[n++] = 8 - k;
536  buffer[n++] = reverseInt8(keyUsage->bitmap & 0xFF);
537  }
538  else
539  {
540  buffer[n++] = 16 - k;
541  buffer[n++] = reverseInt8(keyUsage->bitmap & 0xFF);
542  buffer[n++] = reverseInt8((keyUsage->bitmap >> 8) & 0xFF);
543  }
544 
545  //Format the bit string using ASN.1
546  tag.constructed = FALSE;
549  tag.length = n;
550  tag.value = buffer;
551 
552  //Write the corresponding ASN.1 tag
553  error = asn1WriteTag(&tag, FALSE, p, &n);
554  //Any error to report?
555  if(error)
556  return error;
557 
558  //The extension value is encapsulated in an octet string
559  tag.constructed = FALSE;
562  tag.length = n;
563  tag.value = p;
564 
565  //Write the corresponding ASN.1 tag
566  error = asn1WriteTag(&tag, FALSE, p, &n);
567  //Any error to report?
568  if(error)
569  return error;
570 
571  //Adjust the length of the extension
572  length += n;
573 
574  //The extension is encapsulated within a sequence
575  tag.constructed = TRUE;
578  tag.length = length;
579  tag.value = output;
580 
581  //Write the corresponding ASN.1 tag
582  error = asn1WriteTag(&tag, FALSE, output, &length);
583  //Any error to report?
584  if(error)
585  return error;
586  }
587 
588  //Total number of bytes that have been written
589  *written = length;
590 
591  //Successful processing
592  return NO_ERROR;
593 }
594 
595 
596 /**
597  * @brief Format SubjectAltName extension
598  * @param[in] subjectAltName Value of the extension
599  * @param[out] output Buffer where to format the ASN.1 structure
600  * @param[out] written Length of the resulting ASN.1 structure
601  * @return Error code
602  **/
603 
605  uint8_t *output, size_t *written)
606 {
607  error_t error;
608  uint_t i;
609  size_t n;
610  size_t length;
611  uint8_t *p;
612  Asn1Tag tag;
613 
614  //Initialize status code
615  error = NO_ERROR;
616 
617  //Point to the buffer where to write the ASN.1 structure
618  p = output;
619  //Length of the ASN.1 structure
620  length = 0;
621 
622  //The subject alternative name extension allows identities to be bound to the
623  //subject of the certificate. These identities may be included in addition
624  //to or in place of the identity in the subject field of the certificate
625  if(subjectAltName->numGeneralNames > 0)
626  {
627  //Format the extension identifier
628  tag.constructed = FALSE;
631  tag.length = sizeof(X509_SUBJECT_ALT_NAME_OID);
633 
634  //Write the corresponding ASN.1 tag
635  error = asn1WriteTag(&tag, FALSE, p, &n);
636  //Any error to report?
637  if(error)
638  return error;
639 
640  //Advance data pointer
641  p += n;
642  //Total number of bytes that have been written
643  *written = n;
644 
645  //Loop through subject alternative names
646  for(i = 0; i < subjectAltName->numGeneralNames; i++)
647  {
648  //Format the current name
649  tag.constructed = FALSE;
651  tag.objType = subjectAltName->generalNames[i].type;
652  tag.length = subjectAltName->generalNames[i].length;
653  tag.value = (uint8_t *) subjectAltName->generalNames[i].value;
654 
655  //Write the corresponding ASN.1 tag
656  error = asn1WriteTag(&tag, FALSE, p, &n);
657  //Any error to report?
658  if(error)
659  return error;
660 
661  //Advance data pointer
662  p += n;
663  length += n;
664  }
665 
666  //Point to the first object
667  p = output + *written;
668 
669  //The names are encapsulated within a sequence
670  tag.constructed = TRUE;
673  tag.length = length;
674  tag.value = p;
675 
676  //Write the corresponding ASN.1 tag
677  error = asn1WriteTag(&tag, FALSE, p, &n);
678  //Any error to report?
679  if(error)
680  return error;
681 
682  //The extension value is encapsulated in an octet string
683  tag.constructed = FALSE;
686  tag.length = n;
687  tag.value = p;
688 
689  //Write the corresponding ASN.1 tag
690  error = asn1WriteTag(&tag, FALSE, p, &n);
691  //Any error to report?
692  if(error)
693  return error;
694 
695  //Adjust the length of the extension
696  *written += n;
697 
698  //The extension is encapsulated within a sequence
699  tag.constructed = TRUE;
702  tag.length = *written;
703  tag.value = output;
704 
705  //Write the corresponding ASN.1 tag
706  error = asn1WriteTag(&tag, FALSE, output, &length);
707  //Any error to report?
708  if(error)
709  return error;
710  }
711 
712  //Total number of bytes that have been written
713  *written = length;
714 
715  //Successful processing
716  return NO_ERROR;
717 }
718 
719 
720 /**
721  * @brief Format SubjectKeyIdentifier extension
722  * @param[in] subjectKeyId Value of the extension
723  * @param[out] output Buffer where to format the ASN.1 structure
724  * @param[out] written Length of the resulting ASN.1 structure
725  * @return Error code
726  **/
727 
729  uint8_t *output, size_t *written)
730 {
731  error_t error;
732  size_t n;
733  size_t length;
734  uint8_t *p;
735  Asn1Tag tag;
736 
737  //Initialize status code
738  error = NO_ERROR;
739 
740  //Point to the buffer where to write the ASN.1 structure
741  p = output;
742  //Length of the ASN.1 structure
743  length = 0;
744 
745  //The subject key identifier extension provides a means of identifying
746  //certificates that contain a particular public key
747  if(subjectKeyId->value != NULL && subjectKeyId->length > 0)
748  {
749  //Format the extension identifier
750  tag.constructed = FALSE;
753  tag.length = sizeof(X509_SUBJECT_KEY_ID_OID);
755 
756  //Write the corresponding ASN.1 tag
757  error = asn1WriteTag(&tag, FALSE, p, &n);
758  //Any error to report?
759  if(error)
760  return error;
761 
762  //Advance data pointer
763  p += n;
764  length += n;
765 
766  //Format the KeyIdentifier field
767  tag.constructed = FALSE;
770  tag.length = subjectKeyId->length;
771  tag.value = subjectKeyId->value;
772 
773  //Write the corresponding ASN.1 tag
774  error = asn1WriteTag(&tag, FALSE, p, &n);
775  //Any error to report?
776  if(error)
777  return error;
778 
779  //The extension value is encapsulated in an octet string
780  tag.constructed = FALSE;
783  tag.length = n;
784  tag.value = p;
785 
786  //Write the corresponding ASN.1 tag
787  error = asn1WriteTag(&tag, FALSE, p, &n);
788  //Any error to report?
789  if(error)
790  return error;
791 
792  //Adjust the length of the extension
793  length += n;
794 
795  //The extension is encapsulated within a sequence
796  tag.constructed = TRUE;
799  tag.length = length;
800  tag.value = output;
801 
802  //Write the corresponding ASN.1 tag
803  error = asn1WriteTag(&tag, FALSE, output, &length);
804  //Any error to report?
805  if(error)
806  return error;
807  }
808 
809  //Total number of bytes that have been written
810  *written = length;
811 
812  //Successful processing
813  return NO_ERROR;
814 }
815 
816 
817 /**
818  * @brief Format AuthorityKeyIdentifier extension
819  * @param[in] authKeyId Value of the extension
820  * @param[out] output Buffer where to format the ASN.1 structure
821  * @param[out] written Length of the resulting ASN.1 structure
822  * @return Error code
823  **/
824 
826  uint8_t *output, size_t *written)
827 {
828  error_t error;
829  size_t n;
830  size_t length;
831  uint8_t *p;
832  Asn1Tag tag;
833 
834  //Initialize status code
835  error = NO_ERROR;
836 
837  //Point to the buffer where to write the ASN.1 structure
838  p = output;
839  //Length of the ASN.1 structure
840  length = 0;
841 
842  //The authority key identifier extension provides a means of identifying the
843  //public key corresponding to the private key used to sign a certificate
844  if(authKeyId->keyId.value != NULL && authKeyId->keyId.length > 0)
845  {
846  //Format the extension identifier
847  tag.constructed = FALSE;
850  tag.length = sizeof(X509_AUTHORITY_KEY_ID_OID);
852 
853  //Write the corresponding ASN.1 tag
854  error = asn1WriteTag(&tag, FALSE, p, &n);
855  //Any error to report?
856  if(error)
857  return error;
858 
859  //Advance data pointer
860  p += n;
861  length += n;
862 
863  //Explicit tagging shall be used to encode the keyIdentifier field
864  tag.constructed = FALSE;
866  tag.objType = 0;
867  tag.length = authKeyId->keyId.length;
868  tag.value = authKeyId->keyId.value;
869 
870  //Write the corresponding ASN.1 tag
871  error = asn1WriteTag(&tag, FALSE, p, &n);
872  //Any error to report?
873  if(error)
874  return error;
875 
876  //The KeyIdentifier field is encapsulated within a sequence
877  tag.constructed = TRUE;
880  tag.length = n;
881  tag.value = p;
882 
883  //Write the corresponding ASN.1 tag
884  error = asn1WriteTag(&tag, FALSE, p, &n);
885  //Any error to report?
886  if(error)
887  return error;
888 
889  //The extension value is encapsulated in an octet string
890  tag.constructed = FALSE;
893  tag.length = n;
894  tag.value = p;
895 
896  //Write the corresponding ASN.1 tag
897  error = asn1WriteTag(&tag, FALSE, p, &n);
898  //Any error to report?
899  if(error)
900  return error;
901 
902  //Adjust the length of the extension
903  length += n;
904 
905  //The extension is encapsulated within a sequence
906  tag.constructed = TRUE;
909  tag.length = length;
910  tag.value = output;
911 
912  //Write the corresponding ASN.1 tag
913  error = asn1WriteTag(&tag, FALSE, output, &length);
914  //Any error to report?
915  if(error)
916  return error;
917  }
918 
919  //Total number of bytes that have been written
920  *written = length;
921 
922  //Successful processing
923  return NO_ERROR;
924 }
925 
926 
927 /**
928  * @brief Format NetscapeCertType extension
929  * @param[in] nsCertType Value of the extension
930  * @param[out] output Buffer where to format the ASN.1 structure
931  * @param[out] written Length of the resulting ASN.1 structure
932  * @return Error code
933  **/
934 
936  uint8_t *output, size_t *written)
937 {
938  error_t error;
939  uint_t k;
940  size_t n;
941  size_t length;
942  uint8_t *p;
943  Asn1Tag tag;
944  uint8_t buffer[2];
945 
946  //Initialize status code
947  error = NO_ERROR;
948 
949  //Point to the buffer where to write the ASN.1 structure
950  p = output;
951  //Length of the ASN.1 structure
952  length = 0;
953 
954  //The NetscapeCertType extension limit the use of a certificate
955  if(nsCertType->bitmap != 0)
956  {
957  //Format the extension identifier
958  tag.constructed = FALSE;
961  tag.length = sizeof(X509_NS_CERT_TYPE_OID);
963 
964  //Write the corresponding ASN.1 tag
965  error = asn1WriteTag(&tag, FALSE, p, &n);
966  //Any error to report?
967  if(error)
968  return error;
969 
970  //Advance data pointer
971  p += n;
972  length += n;
973 
974  //Calculate the length, in bits, of the NetscapeCertType value
975  for(k = 8; k > 0; k--)
976  {
977  if(nsCertType->bitmap & (1U << (k - 1)))
978  break;
979  }
980 
981  //Encode bit string value
982  buffer[0] = 8 - k;
983  buffer[1] = reverseInt8(nsCertType->bitmap);
984 
985  //Format the bit string using ASN.1
986  tag.constructed = FALSE;
989  tag.length = sizeof(buffer);
990  tag.value = buffer;
991 
992  //Write the corresponding ASN.1 tag
993  error = asn1WriteTag(&tag, FALSE, p, &n);
994  //Any error to report?
995  if(error)
996  return error;
997 
998  //The extension value is encapsulated in an octet string
999  tag.constructed = FALSE;
1002  tag.length = n;
1003  tag.value = p;
1004 
1005  //Write the corresponding ASN.1 tag
1006  error = asn1WriteTag(&tag, FALSE, p, &n);
1007  //Any error to report?
1008  if(error)
1009  return error;
1010 
1011  //Adjust the length of the extension
1012  length += n;
1013 
1014  //The extension is encapsulated within a sequence
1015  tag.constructed = TRUE;
1018  tag.length = length;
1019  tag.value = output;
1020 
1021  //Write the corresponding ASN.1 tag
1022  error = asn1WriteTag(&tag, FALSE, output, &length);
1023  //Any error to report?
1024  if(error)
1025  return error;
1026  }
1027 
1028  //Total number of bytes that have been written
1029  *written = length;
1030 
1031  //Successful processing
1032  return NO_ERROR;
1033 }
1034 
1035 #endif
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:495
error_t asn1WriteTag(Asn1Tag *tag, bool_t reverse, uint8_t *data, size_t *written)
Write an ASN.1 tag.
Definition: asn1.c:334
ASN.1 (Abstract Syntax Notation One)
@ ASN1_TYPE_OBJECT_IDENTIFIER
Definition: asn1.h:74
@ ASN1_TYPE_BOOLEAN
Definition: asn1.h:69
@ ASN1_TYPE_BIT_STRING
Definition: asn1.h:71
@ ASN1_TYPE_OCTET_STRING
Definition: asn1.h:72
@ ASN1_TYPE_SEQUENCE
Definition: asn1.h:80
#define ASN1_CLASS_UNIVERSAL
Definition: asn1.h:52
#define ASN1_CLASS_CONTEXT_SPECIFIC
Definition: asn1.h:54
unsigned int uint_t
Definition: compiler_port.h:50
uint8_t reverseInt8(uint8_t value)
Reverse bit order in a byte.
Definition: cpu_endian.c:90
General definitions for cryptographic algorithms.
Debugging facilities.
uint8_t n
error_t
Error codes.
Definition: error.h:43
@ NO_ERROR
Success.
Definition: error.h:44
uint8_t p
Definition: ndp.h:300
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
ASN.1 tag.
Definition: asn1.h:102
const uint8_t * value
Definition: asn1.h:107
uint_t objClass
Definition: asn1.h:104
uint_t objType
Definition: asn1.h:105
bool_t constructed
Definition: asn1.h:103
size_t length
Definition: asn1.h:106
Authority Key Identifier extension.
Definition: x509_common.h:889
X509OctetString keyId
Definition: x509_common.h:891
Basic Constraints extension.
Definition: x509_common.h:806
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
X509GeneralNameType type
Definition: x509_common.h:853
const char_t * value
Definition: x509_common.h:854
Key Usage extension.
Definition: x509_common.h:830
uint16_t bitmap
Definition: x509_common.h:832
bool_t critical
Definition: x509_common.h:831
Netscape certificate type.
Definition: x509_common.h:973
uint8_t bitmap
Definition: x509_common.h:975
const uint8_t * value
Definition: x509_common.h:647
Subject Alternative Name extension.
Definition: x509_common.h:864
X509GeneralName generalNames[X509_MAX_SUBJECT_ALT_NAMES]
Definition: x509_common.h:868
Subject Key Identifier extension.
Definition: x509_common.h:877
const uint8_t * value
Definition: x509_common.h:879
uint8_t length
Definition: tcp.h:368
uint8_t value[]
Definition: tcp.h:369
uint8_t extensions[]
Definition: tls13_misc.h:300
error_t x509FormatExtension(const X509Extension *extension, uint8_t *output, size_t *written)
Format X.509 certificate extension.
error_t x509FormatExtensions(const X509Extensions *extensions, const X509SubjectKeyId *subjectKeyId, const X509AuthKeyId *authKeyId, uint8_t *output, size_t *written)
Format Extensions structure.
error_t x509FormatNsCertType(const X509NsCertType *nsCertType, uint8_t *output, size_t *written)
Format NetscapeCertType extension.
error_t x509FormatSubjectAltName(const X509SubjectAltName *subjectAltName, uint8_t *output, size_t *written)
Format SubjectAltName extension.
error_t x509FormatAuthorityKeyId(const X509AuthKeyId *authKeyId, uint8_t *output, size_t *written)
Format AuthorityKeyIdentifier extension.
error_t x509FormatBasicConstraints(const X509BasicConstraints *basicConstraints, uint8_t *output, size_t *written)
Format BasicConstraints extension.
error_t x509FormatKeyUsage(const X509KeyUsage *keyUsage, uint8_t *output, size_t *written)
Format KeyUsage extension.
error_t x509FormatSubjectKeyId(const X509SubjectKeyId *subjectKeyId, uint8_t *output, size_t *written)
Format SubjectKeyIdentifier extension.
X.509 extension formatting.
X.509 certificate formatting.
const uint8_t X509_SUBJECT_KEY_ID_OID[3]
Definition: x509_common.c:81
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_KEY_USAGE_OID[3]
Definition: x509_common.c:83
const uint8_t X509_AUTHORITY_KEY_ID_OID[3]
Definition: x509_common.c:111