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.4
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 ExtendedKeyUsage extension
102  error = x509FormatExtendedKeyUsage(&extensions->extKeyUsage, 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 SubjectKeyId extension
112  error = x509FormatSubjectKeyId(subjectKeyId, 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 AuthorityKeyId extension
122  error = x509FormatAuthorityKeyId(authKeyId, 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  //Format SubjectAltName extension
132  error = x509FormatSubjectAltName(&extensions->subjectAltName, p, &n);
133  //Any error to report?
134  if(error)
135  return error;
136 
137  //Advance data pointer
138  p += n;
139  length += n;
140 
141  //Add custom extensions, if any
142  for(i = 0; i < extensions->numCustomExtensions; i++)
143  {
144  //Format current extension
145  error = x509FormatExtension(&extensions->customExtensions[i], p, &n);
146  //Any error to report?
147  if(error)
148  return error;
149 
150  //Advance data pointer
151  p += n;
152  length += n;
153  }
154 
155  //Any extensions written?
156  if(length > 0)
157  {
158  //The extensions are encapsulated within a sequence
159  tag.constructed = TRUE;
162  tag.length = length;
163  tag.value = output;
164 
165  //Write the corresponding ASN.1 tag
166  error = asn1WriteTag(&tag, FALSE, output, &n);
167  //Any error to report?
168  if(error)
169  return error;
170 
171  //Explicit tagging shall be used to encode the Extensions structure
172  tag.constructed = TRUE;
174  tag.objType = 3;
175  tag.length = n;
176  tag.value = output;
177 
178  //Write the corresponding ASN.1 tag
179  error = asn1WriteTag(&tag, FALSE, output, &length);
180  //Any error to report?
181  if(error)
182  return error;
183  }
184 
185  //Total number of bytes that have been written
186  *written = length;
187 
188  //Successful processing
189  return NO_ERROR;
190 }
191 
192 
193 /**
194  * @brief Format X.509 certificate extension
195  * @param[in] extension Pointer to the extension
196  * @param[out] output Buffer where to format the ASN.1 structure
197  * @param[out] written Length of the resulting ASN.1 structure
198  * @return Error code
199  **/
200 
201 error_t x509FormatExtension(const X509Extension *extension, uint8_t *output,
202  size_t *written)
203 {
204  error_t error;
205  size_t n;
206  size_t length;
207  uint8_t value;
208  uint8_t *p;
209  Asn1Tag tag;
210 
211  //Point to the buffer where to write the ASN.1 structure
212  p = output;
213  //Length of the ASN.1 structure
214  length = 0;
215 
216  //Format the extension identifier
217  tag.constructed = FALSE;
220  tag.length = extension->oid.length;
221  tag.value = extension->oid.value;
222 
223  //Write the corresponding ASN.1 tag
224  error = asn1WriteTag(&tag, FALSE, p, &n);
225  //Any error to report?
226  if(error)
227  return error;
228 
229  //Advance data pointer
230  p += n;
231  length += n;
232 
233  //An extension includes the critical flag, with a default value of FALSE
234  if(extension->critical)
235  {
236  //Mark the extension as critical
237  value = 0xFF;
238 
239  //Format the critical field
240  tag.constructed = FALSE;
243  tag.length = 1;
244  tag.value = &value;
245 
246  //Write the corresponding ASN.1 tag
247  error = asn1WriteTag(&tag, FALSE, p, &n);
248  //Any error to report?
249  if(error)
250  return error;
251 
252  //Advance data pointer
253  p += n;
254  length += n;
255  }
256 
257  //The extension value is encapsulated in an octet string
258  tag.constructed = FALSE;
261  tag.length = extension->data.length;
262  tag.value = extension->data.value;
263 
264  //Write the corresponding ASN.1 tag
265  error = asn1WriteTag(&tag, FALSE, p, &n);
266  //Any error to report?
267  if(error)
268  return error;
269 
270  //Adjust the length of the extension
271  length += n;
272 
273  //The extension is encapsulated within a sequence
274  tag.constructed = TRUE;
277  tag.length = length;
278  tag.value = output;
279 
280  //Write the corresponding ASN.1 tag
281  error = asn1WriteTag(&tag, FALSE, output, &length);
282  //Any error to report?
283  if(error)
284  return error;
285 
286  //Total number of bytes that have been written
287  *written = length;
288 
289  //Successful processing
290  return NO_ERROR;
291 }
292 
293 
294 /**
295  * @brief Format BasicConstraints extension
296  * @param[in] basicConstraints Value of the extension
297  * @param[out] output Buffer where to format the ASN.1 structure
298  * @param[out] written Length of the resulting ASN.1 structure
299  * @return Error code
300  **/
301 
303  uint8_t *output, size_t *written)
304 {
305  error_t error;
306  uint32_t value;
307  size_t n;
308  size_t length;
309  uint8_t *p;
310  Asn1Tag tag;
311  uint8_t buffer[3];
312 
313  //Point to the buffer where to write the ASN.1 structure
314  p = output;
315  //Length of the ASN.1 structure
316  length = 0;
317 
318  //The basic constraints extension identifies whether the subject of the
319  //certificate is a CA and the maximum depth of valid certification paths
320  //that include this certificate
321  if(basicConstraints->cA || basicConstraints->critical)
322  {
323  //Format the extension identifier
324  tag.constructed = FALSE;
327  tag.length = sizeof(X509_BASIC_CONSTRAINTS_OID);
329 
330  //Write the corresponding ASN.1 tag
331  error = asn1WriteTag(&tag, FALSE, p, &n);
332  //Any error to report?
333  if(error)
334  return error;
335 
336  //Advance data pointer
337  p += n;
338  length += n;
339 
340  //An extension includes the critical flag, with a default value of FALSE
341  if(basicConstraints->critical)
342  {
343  //Mark the extension as critical
344  buffer[0] = 0xFF;
345 
346  //Format the critical field
347  tag.constructed = FALSE;
350  tag.length = 1;
351  tag.value = buffer;
352 
353  //Write the corresponding ASN.1 tag
354  error = asn1WriteTag(&tag, FALSE, p, &n);
355  //Any error to report?
356  if(error)
357  return error;
358 
359  //Advance data pointer
360  p += n;
361  length += n;
362  }
363 
364  //Total number of bytes that have been written
365  *written = length;
366 
367  //Length of the extension value
368  length = 0;
369 
370  //Check whether the cA boolean is set
371  if(basicConstraints->cA)
372  {
373  //The cA boolean indicates whether the certified public key may be used
374  //to verify certificate signatures
375  buffer[0] = 0xFF;
376 
377  //Format the cA field
378  tag.constructed = FALSE;
381  tag.length = 1;
382  tag.value = buffer;
383 
384  //Write the corresponding ASN.1 tag
385  error = asn1WriteTag(&tag, FALSE, p, &length);
386  //Any error to report?
387  if(error)
388  return error;
389 
390  //Where pathLenConstraint does not appear, no limit is imposed
391  if(basicConstraints->pathLenConstraint >= 0)
392  {
393  //The pathLenConstraint field gives the maximum number of non-self-issued
394  //intermediate certificates that may follow this certificate in a valid
395  //certification path
396  value = basicConstraints->pathLenConstraint;
397 
398  //Encode pathLenConstraint value
399  error = asn1WriteInt32(value, FALSE, p + length, &n);
400  //Any error to report?
401  if(error)
402  return error;
403 
404  //Update the length of the extension value
405  length += n;
406  }
407  }
408 
409  //The BasicConstraints extension is encapsulated within a sequence
410  tag.constructed = TRUE;
413  tag.length = length;
414  tag.value = p;
415 
416  //Write the corresponding ASN.1 tag
417  error = asn1WriteTag(&tag, FALSE, p, &n);
418  //Any error to report?
419  if(error)
420  return error;
421 
422  //The extension value is encapsulated in an octet string
423  tag.constructed = FALSE;
426  tag.length = n;
427  tag.value = p;
428 
429  //Write the corresponding ASN.1 tag
430  error = asn1WriteTag(&tag, FALSE, output + *written, &n);
431  //Any error to report?
432  if(error)
433  return error;
434 
435  //Adjust the length of the extension
436  *written += n;
437 
438  //The extension is encapsulated within a sequence
439  tag.constructed = TRUE;
442  tag.length = *written;
443  tag.value = output;
444 
445  //Write the corresponding ASN.1 tag
446  error = asn1WriteTag(&tag, FALSE, output, &length);
447  //Any error to report?
448  if(error)
449  return error;
450  }
451 
452  //Total number of bytes that have been written
453  *written = length;
454 
455  //Successful processing
456  return NO_ERROR;
457 }
458 
459 
460 /**
461  * @brief Format KeyUsage extension
462  * @param[in] keyUsage Value of the extension
463  * @param[out] output Buffer where to format the ASN.1 structure
464  * @param[out] written Length of the resulting ASN.1 structure
465  * @return Error code
466  **/
467 
468 error_t x509FormatKeyUsage(const X509KeyUsage *keyUsage, uint8_t *output,
469  size_t *written)
470 {
471  error_t error;
472  uint_t k;
473  size_t n;
474  size_t length;
475  uint8_t *p;
476  Asn1Tag tag;
477  uint8_t buffer[3];
478 
479  //Initialize status code
480  error = NO_ERROR;
481 
482  //Point to the buffer where to write the ASN.1 structure
483  p = output;
484  //Length of the ASN.1 structure
485  length = 0;
486 
487  //The key usage extension defines the purpose of the key contained in the
488  //certificate
489  if(keyUsage->bitmap != 0 || keyUsage->critical)
490  {
491  //Format the extension identifier
492  tag.constructed = FALSE;
495  tag.length = sizeof(X509_KEY_USAGE_OID);
497 
498  //Write the corresponding ASN.1 tag
499  error = asn1WriteTag(&tag, FALSE, p, &n);
500  //Any error to report?
501  if(error)
502  return error;
503 
504  //Advance data pointer
505  p += n;
506  length += n;
507 
508  //An extension includes the critical flag, with a default value of FALSE
509  if(keyUsage->critical)
510  {
511  //Mark the extension as critical
512  buffer[0] = 0xFF;
513 
514  //Format the critical field
515  tag.constructed = FALSE;
518  tag.length = 1;
519  tag.value = buffer;
520 
521  //Write the corresponding ASN.1 tag
522  error = asn1WriteTag(&tag, FALSE, p, &n);
523  //Any error to report?
524  if(error)
525  return error;
526 
527  //Advance data pointer
528  p += n;
529  length += n;
530  }
531 
532  //Calculate the length, in bits, of the KeyUsage value
533  for(k = 16; k > 0; k--)
534  {
535  if(keyUsage->bitmap & (1U << (k - 1)))
536  break;
537  }
538 
539  //Total number of bytes needed to encode the KeyUsage value
540  n = 0;
541 
542  //Encode bit string value
543  if(k <= 8)
544  {
545  buffer[n++] = 8 - k;
546  buffer[n++] = reverseInt8(keyUsage->bitmap & 0xFF);
547  }
548  else
549  {
550  buffer[n++] = 16 - k;
551  buffer[n++] = reverseInt8(keyUsage->bitmap & 0xFF);
552  buffer[n++] = reverseInt8((keyUsage->bitmap >> 8) & 0xFF);
553  }
554 
555  //Format the bit string using ASN.1
556  tag.constructed = FALSE;
559  tag.length = n;
560  tag.value = buffer;
561 
562  //Write the corresponding ASN.1 tag
563  error = asn1WriteTag(&tag, FALSE, p, &n);
564  //Any error to report?
565  if(error)
566  return error;
567 
568  //The extension value is encapsulated in an octet string
569  tag.constructed = FALSE;
572  tag.length = n;
573  tag.value = p;
574 
575  //Write the corresponding ASN.1 tag
576  error = asn1WriteTag(&tag, FALSE, p, &n);
577  //Any error to report?
578  if(error)
579  return error;
580 
581  //Adjust the length of the extension
582  length += n;
583 
584  //The extension is encapsulated within a sequence
585  tag.constructed = TRUE;
588  tag.length = length;
589  tag.value = output;
590 
591  //Write the corresponding ASN.1 tag
592  error = asn1WriteTag(&tag, FALSE, output, &length);
593  //Any error to report?
594  if(error)
595  return error;
596  }
597 
598  //Total number of bytes that have been written
599  *written = length;
600 
601  //Successful processing
602  return NO_ERROR;
603 }
604 
605 
606 /**
607  * @brief Format ExtendedKeyUsage extension
608  * @param[in] keyUsage Value of the extension
609  * @param[out] output Buffer where to format the ASN.1 structure
610  * @param[out] written Length of the resulting ASN.1 structure
611  * @return Error code
612  **/
613 
615  uint8_t *output, size_t *written)
616 {
617  error_t error;
618  size_t n;
619  size_t length;
620  uint8_t value;
621  uint8_t *p;
622  Asn1Tag tag;
623 
624  //Initialize status code
625  error = NO_ERROR;
626 
627  //Point to the buffer where to write the ASN.1 structure
628  p = output;
629  //Length of the ASN.1 structure
630  length = 0;
631 
632  //This extension indicates one or more purposes for which the certified
633  //public key may be used
634  if(extKeyUsage->bitmap != 0)
635  {
636  //Format the extension identifier
637  tag.constructed = FALSE;
640  tag.length = sizeof(X509_EXTENDED_KEY_USAGE_OID);
642 
643  //Write the corresponding ASN.1 tag
644  error = asn1WriteTag(&tag, FALSE, p, &n);
645  //Any error to report?
646  if(error)
647  return error;
648 
649  //Advance data pointer
650  p += n;
651  length += n;
652 
653  //An extension includes the critical flag, with a default value of FALSE
654  if(extKeyUsage->critical)
655  {
656  //Mark the extension as critical
657  value = 0xFF;
658 
659  //Format the critical field
660  tag.constructed = FALSE;
663  tag.length = 1;
664  tag.value = &value;
665 
666  //Write the corresponding ASN.1 tag
667  error = asn1WriteTag(&tag, FALSE, p, &n);
668  //Any error to report?
669  if(error)
670  return error;
671 
672  //Advance data pointer
673  p += n;
674  length += n;
675  }
676 
677  //The extension contains a sequence of KeyPurposeId
678  error = x509FormatKeyPurposes(extKeyUsage->bitmap, p, &n);
679  //Any error to report?
680  if(error)
681  return error;
682 
683  //The extension value is encapsulated in an octet string
684  tag.constructed = FALSE;
687  tag.length = n;
688  tag.value = p;
689 
690  //Write the corresponding ASN.1 tag
691  error = asn1WriteTag(&tag, FALSE, p, &n);
692  //Any error to report?
693  if(error)
694  return error;
695 
696  //Adjust the length of the extension
697  length += n;
698 
699  //The extension is encapsulated within a sequence
700  tag.constructed = TRUE;
703  tag.length = length;
704  tag.value = output;
705 
706  //Write the corresponding ASN.1 tag
707  error = asn1WriteTag(&tag, FALSE, output, &length);
708  //Any error to report?
709  if(error)
710  return error;
711  }
712 
713  //Total number of bytes that have been written
714  *written = length;
715 
716  //Successful processing
717  return NO_ERROR;
718 }
719 
720 
721 /**
722  * @brief Format the list of key purposes
723  * @param[in] bitmap Key purposes
724  * @param[out] output Buffer where to format the ASN.1 structure
725  * @param[out] written Length of the resulting ASN.1 structure
726  * @return Error code
727  **/
728 
729 error_t x509FormatKeyPurposes(uint16_t bitmap, uint8_t *output,
730  size_t *written)
731 {
732  error_t error;
733  uint_t k;
734  size_t n;
735  size_t length;
736  uint8_t *p;
737  Asn1Tag tag;
738 
739  //Point to the buffer where to write the ASN.1 structure
740  p = output;
741  //Length of the ASN.1 structure
742  length = 0;
743 
744  //If a CA includes extended key usages to satisfy such applications, but
745  //does not wish to restrict usages of the key, the CA can include the
746  //special KeyPurposeId anyExtendedKeyUsage
747  if(bitmap == X509_EXT_KEY_USAGE_ANY)
748  {
749  //An object identifier is used to identify a given key purpose
750  tag.constructed = FALSE;
753  tag.length = sizeof(X509_ANY_EXT_KEY_USAGE_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  else
767  {
768  //Format key purposes
769  for(k = 0; k < 16; k++)
770  {
771  //An object identifier is used to identify a given key purpose
772  tag.constructed = FALSE;
775 
776  //Check key purpose
777  switch(bitmap & (1U << k))
778  {
779  //id-kp-serverAuth?
782  tag.length = sizeof(X509_KP_SERVER_AUTH_OID);
783  break;
784 
785  //id-kp-clientAuth?
788  tag.length = sizeof(X509_KP_CLIENT_AUTH_OID);
789  break;
790 
791  //id-kp-codeSigning?
794  tag.length = sizeof(X509_KP_CODE_SIGNING_OID);
795  break;
796 
797  //id-kp-emailProtection?
800  tag.length = sizeof(X509_KP_EMAIL_PROTECTION_OID);
801  break;
802 
803  //id-kp-ipsecEndSystem?
806  tag.length = sizeof(X509_KP_IPSEC_END_SYSTEM_OID);
807  break;
808 
809  //id-kp-ipsecTunnel?
812  tag.length = sizeof(X509_KP_IPSEC_TUNNEL_OID);
813  break;
814 
815  //id-kp-ipsecUser?
818  tag.length = sizeof(X509_KP_IPSEC_USER_OID);
819  break;
820 
821  //id-kp-timeStamping?
824  tag.length = sizeof(X509_KP_TIME_STAMPING_OID);
825  break;
826 
827  //id-kp-OCSPSigning?
830  tag.length = sizeof(X509_KP_OCSP_SIGNING_OID);
831  break;
832 
833  //id-kp-ipsecIKE?
836  tag.length = sizeof(X509_KP_IPSEC_IKE_OID);
837  break;
838 
839  //id-kp-secureShellClient?
842  tag.length = sizeof(X509_KP_SSH_CLIENT_OID);
843  break;
844 
845  //id-kp-secureShellServer?
848  tag.length = sizeof(X509_KP_SSH_SERVER_OID);
849  break;
850 
851  //id-kp-documentSigning?
854  tag.length = sizeof(X509_KP_DOC_SIGNING_OID);
855  break;
856 
857  //Unknown key purpose?
858  default:
859  tag.value = NULL;
860  tag.length = 0;
861  break;
862  }
863 
864  //Valid object identifier?
865  if(tag.value != NULL && tag.length > 0)
866  {
867  //Write the corresponding ASN.1 tag
868  error = asn1WriteTag(&tag, FALSE, p, &n);
869  //Any error to report?
870  if(error)
871  return error;
872 
873  //Advance data pointer
874  p += n;
875  length += n;
876  }
877  }
878  }
879 
880  //The key purposes are encapsulated within a sequence
881  tag.constructed = TRUE;
884  tag.length = length;
885  tag.value = output;
886 
887  //Write the corresponding ASN.1 tag
888  error = asn1WriteTag(&tag, FALSE, output, &length);
889  //Any error to report?
890  if(error)
891  return error;
892 
893  //Total number of bytes that have been written
894  *written = length;
895 
896  //Successful processing
897  return NO_ERROR;
898 }
899 
900 
901 /**
902  * @brief Format SubjectAltName extension
903  * @param[in] subjectAltName Value of the extension
904  * @param[out] output Buffer where to format the ASN.1 structure
905  * @param[out] written Length of the resulting ASN.1 structure
906  * @return Error code
907  **/
908 
910  uint8_t *output, size_t *written)
911 {
912  error_t error;
913  uint_t i;
914  size_t n;
915  size_t length;
916  uint8_t *p;
917  Asn1Tag tag;
918 
919  //Initialize status code
920  error = NO_ERROR;
921 
922  //Point to the buffer where to write the ASN.1 structure
923  p = output;
924  //Length of the ASN.1 structure
925  length = 0;
926 
927  //The subject alternative name extension allows identities to be bound to the
928  //subject of the certificate. These identities may be included in addition
929  //to or in place of the identity in the subject field of the certificate
930  if(subjectAltName->numGeneralNames > 0)
931  {
932  //Format the extension identifier
933  tag.constructed = FALSE;
936  tag.length = sizeof(X509_SUBJECT_ALT_NAME_OID);
938 
939  //Write the corresponding ASN.1 tag
940  error = asn1WriteTag(&tag, FALSE, p, &n);
941  //Any error to report?
942  if(error)
943  return error;
944 
945  //Advance data pointer
946  p += n;
947  //Total number of bytes that have been written
948  *written = n;
949 
950  //Loop through subject alternative names
951  for(i = 0; i < subjectAltName->numGeneralNames; i++)
952  {
953  //Format the current name
954  tag.constructed = FALSE;
956  tag.objType = subjectAltName->generalNames[i].type;
957  tag.length = subjectAltName->generalNames[i].length;
958  tag.value = (uint8_t *) subjectAltName->generalNames[i].value;
959 
960  //Write the corresponding ASN.1 tag
961  error = asn1WriteTag(&tag, FALSE, p, &n);
962  //Any error to report?
963  if(error)
964  return error;
965 
966  //Advance data pointer
967  p += n;
968  length += n;
969  }
970 
971  //Point to the first object
972  p = output + *written;
973 
974  //The names are encapsulated within a sequence
975  tag.constructed = TRUE;
978  tag.length = length;
979  tag.value = p;
980 
981  //Write the corresponding ASN.1 tag
982  error = asn1WriteTag(&tag, FALSE, p, &n);
983  //Any error to report?
984  if(error)
985  return error;
986 
987  //The extension value is encapsulated in an octet string
988  tag.constructed = FALSE;
991  tag.length = n;
992  tag.value = p;
993 
994  //Write the corresponding ASN.1 tag
995  error = asn1WriteTag(&tag, FALSE, p, &n);
996  //Any error to report?
997  if(error)
998  return error;
999 
1000  //Adjust the length of the extension
1001  *written += n;
1002 
1003  //The extension is encapsulated within a sequence
1004  tag.constructed = TRUE;
1007  tag.length = *written;
1008  tag.value = output;
1009 
1010  //Write the corresponding ASN.1 tag
1011  error = asn1WriteTag(&tag, FALSE, output, &length);
1012  //Any error to report?
1013  if(error)
1014  return error;
1015  }
1016 
1017  //Total number of bytes that have been written
1018  *written = length;
1019 
1020  //Successful processing
1021  return NO_ERROR;
1022 }
1023 
1024 
1025 /**
1026  * @brief Format SubjectKeyIdentifier extension
1027  * @param[in] subjectKeyId Value of the extension
1028  * @param[out] output Buffer where to format the ASN.1 structure
1029  * @param[out] written Length of the resulting ASN.1 structure
1030  * @return Error code
1031  **/
1032 
1034  uint8_t *output, size_t *written)
1035 {
1036  error_t error;
1037  size_t n;
1038  size_t length;
1039  uint8_t *p;
1040  Asn1Tag tag;
1041 
1042  //Initialize status code
1043  error = NO_ERROR;
1044 
1045  //Point to the buffer where to write the ASN.1 structure
1046  p = output;
1047  //Length of the ASN.1 structure
1048  length = 0;
1049 
1050  //The subject key identifier extension provides a means of identifying
1051  //certificates that contain a particular public key
1052  if(subjectKeyId->value != NULL && subjectKeyId->length > 0)
1053  {
1054  //Format the extension identifier
1055  tag.constructed = FALSE;
1058  tag.length = sizeof(X509_SUBJECT_KEY_ID_OID);
1060 
1061  //Write the corresponding ASN.1 tag
1062  error = asn1WriteTag(&tag, FALSE, p, &n);
1063  //Any error to report?
1064  if(error)
1065  return error;
1066 
1067  //Advance data pointer
1068  p += n;
1069  length += n;
1070 
1071  //Format the KeyIdentifier field
1072  tag.constructed = FALSE;
1075  tag.length = subjectKeyId->length;
1076  tag.value = subjectKeyId->value;
1077 
1078  //Write the corresponding ASN.1 tag
1079  error = asn1WriteTag(&tag, FALSE, p, &n);
1080  //Any error to report?
1081  if(error)
1082  return error;
1083 
1084  //The extension value is encapsulated in an octet string
1085  tag.constructed = FALSE;
1088  tag.length = n;
1089  tag.value = p;
1090 
1091  //Write the corresponding ASN.1 tag
1092  error = asn1WriteTag(&tag, FALSE, p, &n);
1093  //Any error to report?
1094  if(error)
1095  return error;
1096 
1097  //Adjust the length of the extension
1098  length += n;
1099 
1100  //The extension is encapsulated within a sequence
1101  tag.constructed = TRUE;
1104  tag.length = length;
1105  tag.value = output;
1106 
1107  //Write the corresponding ASN.1 tag
1108  error = asn1WriteTag(&tag, FALSE, output, &length);
1109  //Any error to report?
1110  if(error)
1111  return error;
1112  }
1113 
1114  //Total number of bytes that have been written
1115  *written = length;
1116 
1117  //Successful processing
1118  return NO_ERROR;
1119 }
1120 
1121 
1122 /**
1123  * @brief Format AuthorityKeyIdentifier extension
1124  * @param[in] authKeyId Value of the extension
1125  * @param[out] output Buffer where to format the ASN.1 structure
1126  * @param[out] written Length of the resulting ASN.1 structure
1127  * @return Error code
1128  **/
1129 
1131  uint8_t *output, size_t *written)
1132 {
1133  error_t error;
1134  size_t n;
1135  size_t length;
1136  uint8_t *p;
1137  Asn1Tag tag;
1138 
1139  //Initialize status code
1140  error = NO_ERROR;
1141 
1142  //Point to the buffer where to write the ASN.1 structure
1143  p = output;
1144  //Length of the ASN.1 structure
1145  length = 0;
1146 
1147  //The authority key identifier extension provides a means of identifying the
1148  //public key corresponding to the private key used to sign a certificate
1149  if(authKeyId->keyId.value != NULL && authKeyId->keyId.length > 0)
1150  {
1151  //Format the extension identifier
1152  tag.constructed = FALSE;
1155  tag.length = sizeof(X509_AUTHORITY_KEY_ID_OID);
1157 
1158  //Write the corresponding ASN.1 tag
1159  error = asn1WriteTag(&tag, FALSE, p, &n);
1160  //Any error to report?
1161  if(error)
1162  return error;
1163 
1164  //Advance data pointer
1165  p += n;
1166  length += n;
1167 
1168  //Explicit tagging shall be used to encode the keyIdentifier field
1169  tag.constructed = FALSE;
1171  tag.objType = 0;
1172  tag.length = authKeyId->keyId.length;
1173  tag.value = authKeyId->keyId.value;
1174 
1175  //Write the corresponding ASN.1 tag
1176  error = asn1WriteTag(&tag, FALSE, p, &n);
1177  //Any error to report?
1178  if(error)
1179  return error;
1180 
1181  //The KeyIdentifier field is encapsulated within a sequence
1182  tag.constructed = TRUE;
1185  tag.length = n;
1186  tag.value = p;
1187 
1188  //Write the corresponding ASN.1 tag
1189  error = asn1WriteTag(&tag, FALSE, p, &n);
1190  //Any error to report?
1191  if(error)
1192  return error;
1193 
1194  //The extension value is encapsulated in an octet string
1195  tag.constructed = FALSE;
1198  tag.length = n;
1199  tag.value = p;
1200 
1201  //Write the corresponding ASN.1 tag
1202  error = asn1WriteTag(&tag, FALSE, p, &n);
1203  //Any error to report?
1204  if(error)
1205  return error;
1206 
1207  //Adjust the length of the extension
1208  length += n;
1209 
1210  //The extension is encapsulated within a sequence
1211  tag.constructed = TRUE;
1214  tag.length = length;
1215  tag.value = output;
1216 
1217  //Write the corresponding ASN.1 tag
1218  error = asn1WriteTag(&tag, FALSE, output, &length);
1219  //Any error to report?
1220  if(error)
1221  return error;
1222  }
1223 
1224  //Total number of bytes that have been written
1225  *written = length;
1226 
1227  //Successful processing
1228  return NO_ERROR;
1229 }
1230 
1231 
1232 /**
1233  * @brief Format NetscapeCertType extension
1234  * @param[in] nsCertType Value of the extension
1235  * @param[out] output Buffer where to format the ASN.1 structure
1236  * @param[out] written Length of the resulting ASN.1 structure
1237  * @return Error code
1238  **/
1239 
1241  uint8_t *output, size_t *written)
1242 {
1243  error_t error;
1244  uint_t k;
1245  size_t n;
1246  size_t length;
1247  uint8_t *p;
1248  Asn1Tag tag;
1249  uint8_t buffer[2];
1250 
1251  //Initialize status code
1252  error = NO_ERROR;
1253 
1254  //Point to the buffer where to write the ASN.1 structure
1255  p = output;
1256  //Length of the ASN.1 structure
1257  length = 0;
1258 
1259  //The NetscapeCertType extension limit the use of a certificate
1260  if(nsCertType->bitmap != 0)
1261  {
1262  //Format the extension identifier
1263  tag.constructed = FALSE;
1266  tag.length = sizeof(X509_NS_CERT_TYPE_OID);
1268 
1269  //Write the corresponding ASN.1 tag
1270  error = asn1WriteTag(&tag, FALSE, p, &n);
1271  //Any error to report?
1272  if(error)
1273  return error;
1274 
1275  //Advance data pointer
1276  p += n;
1277  length += n;
1278 
1279  //Calculate the length, in bits, of the NetscapeCertType value
1280  for(k = 8; k > 0; k--)
1281  {
1282  if(nsCertType->bitmap & (1U << (k - 1)))
1283  break;
1284  }
1285 
1286  //Encode bit string value
1287  buffer[0] = 8 - k;
1288  buffer[1] = reverseInt8(nsCertType->bitmap);
1289 
1290  //Format the bit string using ASN.1
1291  tag.constructed = FALSE;
1294  tag.length = sizeof(buffer);
1295  tag.value = buffer;
1296 
1297  //Write the corresponding ASN.1 tag
1298  error = asn1WriteTag(&tag, FALSE, p, &n);
1299  //Any error to report?
1300  if(error)
1301  return error;
1302 
1303  //The extension value is encapsulated in an octet string
1304  tag.constructed = FALSE;
1307  tag.length = n;
1308  tag.value = p;
1309 
1310  //Write the corresponding ASN.1 tag
1311  error = asn1WriteTag(&tag, FALSE, p, &n);
1312  //Any error to report?
1313  if(error)
1314  return error;
1315 
1316  //Adjust the length of the extension
1317  length += n;
1318 
1319  //The extension is encapsulated within a sequence
1320  tag.constructed = TRUE;
1323  tag.length = length;
1324  tag.value = output;
1325 
1326  //Write the corresponding ASN.1 tag
1327  error = asn1WriteTag(&tag, FALSE, output, &length);
1328  //Any error to report?
1329  if(error)
1330  return error;
1331  }
1332 
1333  //Total number of bytes that have been written
1334  *written = length;
1335 
1336  //Successful processing
1337  return NO_ERROR;
1338 }
1339 
1340 #endif
@ X509_EXT_KEY_USAGE_ANY
Definition: x509_common.h:509
error_t x509FormatSubjectKeyId(const X509SubjectKeyId *subjectKeyId, uint8_t *output, size_t *written)
Format SubjectKeyIdentifier extension.
uint8_t extensions[]
Definition: ntp_common.h:207
@ X509_EXT_KEY_USAGE_SSH_CLIENT
Definition: x509_common.h:506
X509GeneralNameType type
Definition: x509_common.h:860
@ X509_EXT_KEY_USAGE_IPSEC_IKE
Definition: x509_common.h:505
const uint8_t X509_KP_DOC_SIGNING_OID[8]
Definition: x509_common.c:154
const uint8_t X509_KP_SERVER_AUTH_OID[8]
Definition: x509_common.c:130
const uint8_t X509_SUBJECT_ALT_NAME_OID[3]
Definition: x509_common.c:85
error_t x509FormatExtensions(const X509Extensions *extensions, const X509SubjectKeyId *subjectKeyId, const X509AuthKeyId *authKeyId, uint8_t *output, size_t *written)
Format Extensions structure.
const uint8_t X509_KP_CODE_SIGNING_OID[8]
Definition: x509_common.c:134
uint8_t p
Definition: ndp.h:300
error_t x509FormatBasicConstraints(const X509BasicConstraints *basicConstraints, uint8_t *output, size_t *written)
Format BasicConstraints extension.
#define TRUE
Definition: os_port.h:50
bool_t critical
Definition: x509_common.h:993
const uint8_t X509_EXTENDED_KEY_USAGE_OID[3]
Definition: x509_common.c:115
const uint8_t X509_ANY_EXT_KEY_USAGE_OID[4]
Definition: x509_common.c:128
const uint8_t X509_KEY_USAGE_OID[3]
Definition: x509_common.c:83
const uint8_t X509_KP_TIME_STAMPING_OID[8]
Definition: x509_common.c:144
@ X509_EXT_KEY_USAGE_IPSEC_USER
Definition: x509_common.h:502
@ X509_EXT_KEY_USAGE_CLIENT_AUTH
Definition: x509_common.h:497
@ X509_EXT_KEY_USAGE_SSH_SERVER
Definition: x509_common.h:507
@ X509_EXT_KEY_USAGE_IPSEC_END_SYSTEM
Definition: x509_common.h:500
const uint8_t X509_KP_OCSP_SIGNING_OID[8]
Definition: x509_common.c:146
Subject Key Identifier extension.
Definition: x509_common.h:884
X.509 certificate formatting.
error_t x509FormatSubjectAltName(const X509SubjectAltName *subjectAltName, uint8_t *output, size_t *written)
Format SubjectAltName extension.
const uint8_t X509_BASIC_CONSTRAINTS_OID[3]
Definition: x509_common.c:89
size_t length
Definition: asn1.h:106
#define FALSE
Definition: os_port.h:46
bool_t critical
Definition: x509_common.h:838
error_t
Error codes.
Definition: error.h:43
Extended Key Usage extension.
Definition: x509_common.h:848
#define ASN1_CLASS_UNIVERSAL
Definition: asn1.h:52
ASN.1 tag.
Definition: asn1.h:102
const uint8_t X509_KP_EMAIL_PROTECTION_OID[8]
Definition: x509_common.c:136
X.509 certificate extension.
Definition: x509_common.h:991
const uint8_t X509_AUTHORITY_KEY_ID_OID[3]
Definition: x509_common.c:111
Authority Key Identifier extension.
Definition: x509_common.h:896
General definitions for cryptographic algorithms.
const uint8_t X509_KP_IPSEC_USER_OID[8]
Definition: x509_common.c:142
error_t asn1WriteTag(Asn1Tag *tag, bool_t reverse, uint8_t *data, size_t *written)
Write an ASN.1 tag.
Definition: asn1.c:334
@ X509_EXT_KEY_USAGE_SERVER_AUTH
Definition: x509_common.h:496
uint_t objClass
Definition: asn1.h:104
const uint8_t X509_KP_IPSEC_IKE_OID[8]
Definition: x509_common.c:148
uint8_t length
Definition: tcp.h:368
uint16_t bitmap
Definition: x509_common.h:839
const uint8_t X509_KP_CLIENT_AUTH_OID[8]
Definition: x509_common.c:132
Subject Alternative Name extension.
Definition: x509_common.h:871
@ X509_EXT_KEY_USAGE_DOC_SIGNING
Definition: x509_common.h:508
@ X509_EXT_KEY_USAGE_TIME_STAMPING
Definition: x509_common.h:503
Netscape certificate type.
Definition: x509_common.h:980
@ X509_EXT_KEY_USAGE_IPSEC_TUNNEL
Definition: x509_common.h:501
error_t x509FormatKeyPurposes(uint16_t bitmap, uint8_t *output, size_t *written)
Format the list of key purposes.
const char_t * value
Definition: x509_common.h:861
@ ASN1_TYPE_OCTET_STRING
Definition: asn1.h:72
const uint8_t X509_KP_SSH_SERVER_OID[8]
Definition: x509_common.c:152
error_t x509FormatAuthorityKeyId(const X509AuthKeyId *authKeyId, uint8_t *output, size_t *written)
Format AuthorityKeyIdentifier extension.
error_t x509FormatExtension(const X509Extension *extension, uint8_t *output, size_t *written)
Format X.509 certificate extension.
uint8_t n
#define ASN1_CLASS_CONTEXT_SPECIFIC
Definition: asn1.h:54
const uint8_t X509_NS_CERT_TYPE_OID[9]
Definition: x509_common.c:125
uint8_t value[]
Definition: tcp.h:369
Basic Constraints extension.
Definition: x509_common.h:813
uint8_t reverseInt8(uint8_t value)
Reverse bit order in a byte.
Definition: cpu_endian.c:90
bool_t constructed
Definition: asn1.h:103
error_t x509FormatKeyUsage(const X509KeyUsage *keyUsage, uint8_t *output, size_t *written)
Format KeyUsage extension.
@ X509_EXT_KEY_USAGE_OCSP_SIGNING
Definition: x509_common.h:504
const uint8_t X509_KP_IPSEC_TUNNEL_OID[8]
Definition: x509_common.c:140
@ ASN1_TYPE_OBJECT_IDENTIFIER
Definition: asn1.h:74
@ ASN1_TYPE_SEQUENCE
Definition: asn1.h:80
X.509 certificate extensions.
Definition: x509_common.h:1003
X509OctetString oid
Definition: x509_common.h:992
@ X509_EXT_KEY_USAGE_CODE_SIGNING
Definition: x509_common.h:498
const uint8_t X509_SUBJECT_KEY_ID_OID[3]
Definition: x509_common.c:81
const uint8_t * value
Definition: x509_common.h:654
const uint8_t * value
Definition: x509_common.h:886
const uint8_t X509_KP_IPSEC_END_SYSTEM_OID[8]
Definition: x509_common.c:138
@ ASN1_TYPE_BIT_STRING
Definition: asn1.h:71
X.509 extension formatting.
X509OctetString keyId
Definition: x509_common.h:898
unsigned int uint_t
Definition: compiler_port.h:50
error_t x509FormatNsCertType(const X509NsCertType *nsCertType, uint8_t *output, size_t *written)
Format NetscapeCertType extension.
uint8_t bitmap
Definition: x509_common.h:982
X509OctetString data
Definition: x509_common.h:994
error_t x509FormatExtendedKeyUsage(const X509ExtendedKeyUsage *extKeyUsage, uint8_t *output, size_t *written)
Format ExtendedKeyUsage extension.
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
@ ASN1_TYPE_BOOLEAN
Definition: asn1.h:69
@ X509_EXT_KEY_USAGE_EMAIL_PROTECTION
Definition: x509_common.h:499
X509GeneralName generalNames[X509_MAX_SUBJECT_ALT_NAMES]
Definition: x509_common.h:875
const uint8_t * value
Definition: asn1.h:107
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
uint_t objType
Definition: asn1.h:105
ASN.1 (Abstract Syntax Notation One)
const uint8_t X509_KP_SSH_CLIENT_OID[8]
Definition: x509_common.c:150
Key Usage extension.
Definition: x509_common.h:837