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-2025 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneCRYPTO Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.5.2
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
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
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
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  ASN1_INC_POINTER(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  ASN1_INC_POINTER(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  ASN1_INC_POINTER(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  ASN1_INC_POINTER(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  ASN1_INC_POINTER(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 
164  //Write the corresponding ASN.1 tag
165  error = asn1InsertHeader(&tag, output, &n);
166  //Any error to report?
167  if(error)
168  return error;
169 
170  //Get the length of the resulting sequence
171  length = tag.totalLength;
172 
173  //Explicit tagging shall be used to encode the Extensions structure
174  tag.constructed = TRUE;
176  tag.objType = 3;
177  tag.length = length;
178 
179  //Write the corresponding ASN.1 tag
180  error = asn1InsertHeader(&tag, output, &n);
181  //Any error to report?
182  if(error)
183  return error;
184 
185  //Get the length of the resulting tag
186  length = tag.totalLength;
187  }
188 
189  //Total number of bytes that have been written
190  *written = length;
191 
192  //Successful processing
193  return NO_ERROR;
194 }
195 
196 
197 /**
198  * @brief Format X.509 certificate extension
199  * @param[in] extension Pointer to the extension
200  * @param[out] output Buffer where to format the ASN.1 structure
201  * @param[out] written Length of the resulting ASN.1 structure
202  * @return Error code
203  **/
204 
205 error_t x509FormatExtension(const X509Extension *extension, uint8_t *output,
206  size_t *written)
207 {
208  error_t error;
209  size_t n;
210  size_t length;
211  uint8_t value;
212  uint8_t *p;
213  Asn1Tag tag;
214 
215  //Point to the buffer where to write the ASN.1 structure
216  p = output;
217  //Length of the ASN.1 structure
218  length = 0;
219 
220  //Format the extension identifier
221  tag.constructed = FALSE;
224  tag.length = extension->oid.length;
225  tag.value = extension->oid.value;
226 
227  //Write the corresponding ASN.1 tag
228  error = asn1WriteTag(&tag, FALSE, p, &n);
229  //Any error to report?
230  if(error)
231  return error;
232 
233  //Advance data pointer
234  ASN1_INC_POINTER(p, n);
235  length += n;
236 
237  //An extension includes the critical flag, with a default value of FALSE
238  if(extension->critical)
239  {
240  //Mark the extension as critical
241  value = 0xFF;
242 
243  //Format the critical field
244  tag.constructed = FALSE;
247  tag.length = 1;
248  tag.value = &value;
249 
250  //Write the corresponding ASN.1 tag
251  error = asn1WriteTag(&tag, FALSE, p, &n);
252  //Any error to report?
253  if(error)
254  return error;
255 
256  //Advance data pointer
257  ASN1_INC_POINTER(p, n);
258  length += n;
259  }
260 
261  //The extension value is encapsulated in an octet string
262  tag.constructed = FALSE;
265  tag.length = extension->data.length;
266  tag.value = extension->data.value;
267 
268  //Write the corresponding ASN.1 tag
269  error = asn1WriteTag(&tag, FALSE, p, &n);
270  //Any error to report?
271  if(error)
272  return error;
273 
274  //Adjust the length of the extension
275  length += n;
276 
277  //The extension is encapsulated within a sequence
278  tag.constructed = TRUE;
281  tag.length = length;
282 
283  //Write the corresponding ASN.1 tag
284  error = asn1InsertHeader(&tag, output, &n);
285  //Any error to report?
286  if(error)
287  return error;
288 
289  //Total number of bytes that have been written
290  *written = tag.totalLength;
291 
292  //Successful processing
293  return NO_ERROR;
294 }
295 
296 
297 /**
298  * @brief Format BasicConstraints extension
299  * @param[in] basicConstraints Value of the extension
300  * @param[out] output Buffer where to format the ASN.1 structure
301  * @param[out] written Length of the resulting ASN.1 structure
302  * @return Error code
303  **/
304 
306  uint8_t *output, size_t *written)
307 {
308  error_t error;
309  uint32_t value;
310  size_t n;
311  size_t length;
312  uint8_t *p;
313  Asn1Tag tag;
314  uint8_t buffer[3];
315 
316  //Point to the buffer where to write the ASN.1 structure
317  p = output;
318  //Length of the ASN.1 structure
319  length = 0;
320 
321  //The basic constraints extension identifies whether the subject of the
322  //certificate is a CA and the maximum depth of valid certification paths
323  //that include this certificate
324  if(basicConstraints->cA || basicConstraints->critical)
325  {
326  //Format the extension identifier
327  tag.constructed = FALSE;
330  tag.length = sizeof(X509_BASIC_CONSTRAINTS_OID);
332 
333  //Write the corresponding ASN.1 tag
334  error = asn1WriteTag(&tag, FALSE, p, &n);
335  //Any error to report?
336  if(error)
337  return error;
338 
339  //Advance data pointer
340  ASN1_INC_POINTER(p, n);
341  length += n;
342 
343  //An extension includes the critical flag, with a default value of FALSE
344  if(basicConstraints->critical)
345  {
346  //Mark the extension as critical
347  buffer[0] = 0xFF;
348 
349  //Format the critical field
350  tag.constructed = FALSE;
353  tag.length = 1;
354  tag.value = buffer;
355 
356  //Write the corresponding ASN.1 tag
357  error = asn1WriteTag(&tag, FALSE, p, &n);
358  //Any error to report?
359  if(error)
360  return error;
361 
362  //Advance data pointer
363  ASN1_INC_POINTER(p, n);
364  length += n;
365  }
366 
367  //Total number of bytes that have been written
368  *written = length;
369 
370  //Length of the extension value
371  length = 0;
372 
373  //Check whether the cA boolean is set
374  if(basicConstraints->cA)
375  {
376  //The cA boolean indicates whether the certified public key may be used
377  //to verify certificate signatures
378  buffer[0] = 0xFF;
379 
380  //Format the cA field
381  tag.constructed = FALSE;
384  tag.length = 1;
385  tag.value = buffer;
386 
387  //Write the corresponding ASN.1 tag
388  error = asn1WriteTag(&tag, FALSE, p, &n);
389  //Any error to report?
390  if(error)
391  return error;
392 
393  //Advance data pointer
394  ASN1_INC_POINTER(p, n);
395  length += n;
396 
397  //Where pathLenConstraint does not appear, no limit is imposed
398  if(basicConstraints->pathLenConstraint >= 0)
399  {
400  //The pathLenConstraint field gives the maximum number of non-self-issued
401  //intermediate certificates that may follow this certificate in a valid
402  //certification path
403  value = basicConstraints->pathLenConstraint;
404 
405  //Encode pathLenConstraint value
406  error = asn1WriteInt32(value, FALSE, p, &n);
407  //Any error to report?
408  if(error)
409  return error;
410 
411  //Advance data pointer
412  ASN1_INC_POINTER(p, n);
413  length += n;
414  }
415  }
416 
417  //Point to the BasicConstraints extension
418  if(output != NULL)
419  {
420  p = output + *written;
421  }
422  else
423  {
424  p = NULL;
425  }
426 
427  //The BasicConstraints extension is encapsulated within a sequence
428  tag.constructed = TRUE;
431  tag.length = length;
432 
433  //Write the corresponding ASN.1 tag
434  error = asn1InsertHeader(&tag, p, &n);
435  //Any error to report?
436  if(error)
437  return error;
438 
439  //Get the length of the resulting sequence
440  length = tag.totalLength;
441 
442  //The extension value is encapsulated in an octet string
443  tag.constructed = FALSE;
446  tag.length = length;
447 
448  //Write the corresponding ASN.1 tag
449  error = asn1InsertHeader(&tag, p, &n);
450  //Any error to report?
451  if(error)
452  return error;
453 
454  //Adjust the length of the extension
455  *written += tag.totalLength;
456 
457  //The extension is encapsulated within a sequence
458  tag.constructed = TRUE;
461  tag.length = *written;
462 
463  //Write the corresponding ASN.1 tag
464  error = asn1InsertHeader(&tag, output, &n);
465  //Any error to report?
466  if(error)
467  return error;
468 
469  //Get the length of the resulting sequence
470  length = tag.totalLength;
471  }
472 
473  //Total number of bytes that have been written
474  *written = length;
475 
476  //Successful processing
477  return NO_ERROR;
478 }
479 
480 
481 /**
482  * @brief Format KeyUsage extension
483  * @param[in] keyUsage Value of the extension
484  * @param[out] output Buffer where to format the ASN.1 structure
485  * @param[out] written Length of the resulting ASN.1 structure
486  * @return Error code
487  **/
488 
489 error_t x509FormatKeyUsage(const X509KeyUsage *keyUsage, uint8_t *output,
490  size_t *written)
491 {
492  error_t error;
493  uint_t k;
494  size_t n;
495  size_t length;
496  uint8_t *p;
497  Asn1Tag tag;
498  uint8_t buffer[3];
499 
500  //Initialize status code
501  error = NO_ERROR;
502 
503  //Point to the buffer where to write the ASN.1 structure
504  p = output;
505  //Length of the ASN.1 structure
506  length = 0;
507 
508  //The key usage extension defines the purpose of the key contained in the
509  //certificate
510  if(keyUsage->bitmap != 0 || keyUsage->critical)
511  {
512  //Format the extension identifier
513  tag.constructed = FALSE;
516  tag.length = sizeof(X509_KEY_USAGE_OID);
518 
519  //Write the corresponding ASN.1 tag
520  error = asn1WriteTag(&tag, FALSE, p, &n);
521  //Any error to report?
522  if(error)
523  return error;
524 
525  //Advance data pointer
526  ASN1_INC_POINTER(p, n);
527  length += n;
528 
529  //An extension includes the critical flag, with a default value of FALSE
530  if(keyUsage->critical)
531  {
532  //Mark the extension as critical
533  buffer[0] = 0xFF;
534 
535  //Format the critical field
536  tag.constructed = FALSE;
539  tag.length = 1;
540  tag.value = buffer;
541 
542  //Write the corresponding ASN.1 tag
543  error = asn1WriteTag(&tag, FALSE, p, &n);
544  //Any error to report?
545  if(error)
546  return error;
547 
548  //Advance data pointer
549  ASN1_INC_POINTER(p, n);
550  length += n;
551  }
552 
553  //Calculate the length, in bits, of the KeyUsage value
554  for(k = 16; k > 0; k--)
555  {
556  if(keyUsage->bitmap & (1U << (k - 1)))
557  break;
558  }
559 
560  //Total number of bytes needed to encode the KeyUsage value
561  n = 0;
562 
563  //Encode bit string value
564  if(k <= 8)
565  {
566  buffer[n++] = 8 - k;
567  buffer[n++] = reverseInt8(keyUsage->bitmap & 0xFF);
568  }
569  else
570  {
571  buffer[n++] = 16 - k;
572  buffer[n++] = reverseInt8(keyUsage->bitmap & 0xFF);
573  buffer[n++] = reverseInt8((keyUsage->bitmap >> 8) & 0xFF);
574  }
575 
576  //Format the bit string using ASN.1
577  tag.constructed = FALSE;
580  tag.length = n;
581  tag.value = buffer;
582 
583  //Write the corresponding ASN.1 tag
584  error = asn1WriteTag(&tag, FALSE, p, &n);
585  //Any error to report?
586  if(error)
587  return error;
588 
589  //The extension value is encapsulated in an octet string
590  tag.constructed = FALSE;
593  tag.length = n;
594 
595  //Write the corresponding ASN.1 tag
596  error = asn1InsertHeader(&tag, p, &n);
597  //Any error to report?
598  if(error)
599  return error;
600 
601  //Adjust the length of the extension
602  length += tag.totalLength;
603 
604  //The extension is encapsulated within a sequence
605  tag.constructed = TRUE;
608  tag.length = length;
609 
610  //Write the corresponding ASN.1 tag
611  error = asn1InsertHeader(&tag, output, &n);
612  //Any error to report?
613  if(error)
614  return error;
615 
616  //Get the length of the resulting sequence
617  length = tag.totalLength;
618  }
619 
620  //Total number of bytes that have been written
621  *written = length;
622 
623  //Successful processing
624  return NO_ERROR;
625 }
626 
627 
628 /**
629  * @brief Format ExtendedKeyUsage extension
630  * @param[in] extKeyUsage Value of the extension
631  * @param[out] output Buffer where to format the ASN.1 structure
632  * @param[out] written Length of the resulting ASN.1 structure
633  * @return Error code
634  **/
635 
637  uint8_t *output, size_t *written)
638 {
639  error_t error;
640  size_t n;
641  size_t length;
642  uint8_t value;
643  uint8_t *p;
644  Asn1Tag tag;
645 
646  //Initialize status code
647  error = NO_ERROR;
648 
649  //Point to the buffer where to write the ASN.1 structure
650  p = output;
651  //Length of the ASN.1 structure
652  length = 0;
653 
654  //This extension indicates one or more purposes for which the certified
655  //public key may be used
656  if(extKeyUsage->bitmap != 0)
657  {
658  //Format the extension identifier
659  tag.constructed = FALSE;
662  tag.length = sizeof(X509_EXTENDED_KEY_USAGE_OID);
664 
665  //Write the corresponding ASN.1 tag
666  error = asn1WriteTag(&tag, FALSE, p, &n);
667  //Any error to report?
668  if(error)
669  return error;
670 
671  //Advance data pointer
672  ASN1_INC_POINTER(p, n);
673  length += n;
674 
675  //An extension includes the critical flag, with a default value of FALSE
676  if(extKeyUsage->critical)
677  {
678  //Mark the extension as critical
679  value = 0xFF;
680 
681  //Format the critical field
682  tag.constructed = FALSE;
685  tag.length = 1;
686  tag.value = &value;
687 
688  //Write the corresponding ASN.1 tag
689  error = asn1WriteTag(&tag, FALSE, p, &n);
690  //Any error to report?
691  if(error)
692  return error;
693 
694  //Advance data pointer
695  ASN1_INC_POINTER(p, n);
696  length += n;
697  }
698 
699  //The extension contains a sequence of KeyPurposeId
700  error = x509FormatKeyPurposes(extKeyUsage->bitmap, p, &n);
701  //Any error to report?
702  if(error)
703  return error;
704 
705  //The extension value is encapsulated in an octet string
706  tag.constructed = FALSE;
709  tag.length = n;
710 
711  //Write the corresponding ASN.1 tag
712  error = asn1InsertHeader(&tag, p, &n);
713  //Any error to report?
714  if(error)
715  return error;
716 
717  //Adjust the length of the extension
718  length += tag.totalLength;
719 
720  //The extension is encapsulated within a sequence
721  tag.constructed = TRUE;
724  tag.length = length;
725 
726  //Write the corresponding ASN.1 tag
727  error = asn1InsertHeader(&tag, output, &n);
728  //Any error to report?
729  if(error)
730  return error;
731 
732  //Get the length of the resulting sequence
733  length = tag.totalLength;
734  }
735 
736  //Total number of bytes that have been written
737  *written = length;
738 
739  //Successful processing
740  return NO_ERROR;
741 }
742 
743 
744 /**
745  * @brief Format the list of key purposes
746  * @param[in] bitmap Key purposes
747  * @param[out] output Buffer where to format the ASN.1 structure
748  * @param[out] written Length of the resulting ASN.1 structure
749  * @return Error code
750  **/
751 
752 error_t x509FormatKeyPurposes(uint16_t bitmap, uint8_t *output,
753  size_t *written)
754 {
755  error_t error;
756  uint_t k;
757  size_t n;
758  size_t length;
759  uint8_t *p;
760  Asn1Tag tag;
761 
762  //Point to the buffer where to write the ASN.1 structure
763  p = output;
764  //Length of the ASN.1 structure
765  length = 0;
766 
767  //If a CA includes extended key usages to satisfy such applications, but
768  //does not wish to restrict usages of the key, the CA can include the
769  //special KeyPurposeId anyExtendedKeyUsage
770  if(bitmap == X509_EXT_KEY_USAGE_ANY)
771  {
772  //An object identifier is used to identify a given key purpose
773  tag.constructed = FALSE;
776  tag.length = sizeof(X509_ANY_EXT_KEY_USAGE_OID);
778 
779  //Write the corresponding ASN.1 tag
780  error = asn1WriteTag(&tag, FALSE, p, &n);
781  //Any error to report?
782  if(error)
783  return error;
784 
785  //Advance data pointer
786  ASN1_INC_POINTER(p, n);
787  length += n;
788  }
789  else
790  {
791  //Format key purposes
792  for(k = 0; k < 16; k++)
793  {
794  //An object identifier is used to identify a given key purpose
795  tag.constructed = FALSE;
798 
799  //Check key purpose
800  switch(bitmap & (1U << k))
801  {
802  //id-kp-serverAuth?
805  tag.length = sizeof(X509_KP_SERVER_AUTH_OID);
806  break;
807 
808  //id-kp-clientAuth?
811  tag.length = sizeof(X509_KP_CLIENT_AUTH_OID);
812  break;
813 
814  //id-kp-codeSigning?
817  tag.length = sizeof(X509_KP_CODE_SIGNING_OID);
818  break;
819 
820  //id-kp-emailProtection?
823  tag.length = sizeof(X509_KP_EMAIL_PROTECTION_OID);
824  break;
825 
826  //id-kp-ipsecEndSystem?
829  tag.length = sizeof(X509_KP_IPSEC_END_SYSTEM_OID);
830  break;
831 
832  //id-kp-ipsecTunnel?
835  tag.length = sizeof(X509_KP_IPSEC_TUNNEL_OID);
836  break;
837 
838  //id-kp-ipsecUser?
841  tag.length = sizeof(X509_KP_IPSEC_USER_OID);
842  break;
843 
844  //id-kp-timeStamping?
847  tag.length = sizeof(X509_KP_TIME_STAMPING_OID);
848  break;
849 
850  //id-kp-OCSPSigning?
853  tag.length = sizeof(X509_KP_OCSP_SIGNING_OID);
854  break;
855 
856  //id-kp-ipsecIKE?
859  tag.length = sizeof(X509_KP_IPSEC_IKE_OID);
860  break;
861 
862  //id-kp-secureShellClient?
865  tag.length = sizeof(X509_KP_SSH_CLIENT_OID);
866  break;
867 
868  //id-kp-secureShellServer?
871  tag.length = sizeof(X509_KP_SSH_SERVER_OID);
872  break;
873 
874  //id-kp-documentSigning?
877  tag.length = sizeof(X509_KP_DOC_SIGNING_OID);
878  break;
879 
880  //Unknown key purpose?
881  default:
882  tag.value = NULL;
883  tag.length = 0;
884  break;
885  }
886 
887  //Valid object identifier?
888  if(tag.value != NULL && tag.length > 0)
889  {
890  //Write the corresponding ASN.1 tag
891  error = asn1WriteTag(&tag, FALSE, p, &n);
892  //Any error to report?
893  if(error)
894  return error;
895 
896  //Advance data pointer
897  ASN1_INC_POINTER(p, n);
898  length += n;
899  }
900  }
901  }
902 
903  //The key purposes are encapsulated within a sequence
904  tag.constructed = TRUE;
907  tag.length = length;
908 
909  //Write the corresponding ASN.1 tag
910  error = asn1InsertHeader(&tag, output, &n);
911  //Any error to report?
912  if(error)
913  return error;
914 
915  //Total number of bytes that have been written
916  *written = tag.totalLength;
917 
918  //Successful processing
919  return NO_ERROR;
920 }
921 
922 
923 /**
924  * @brief Format SubjectAltName extension
925  * @param[in] subjectAltName Value of the extension
926  * @param[out] output Buffer where to format the ASN.1 structure
927  * @param[out] written Length of the resulting ASN.1 structure
928  * @return Error code
929  **/
930 
932  uint8_t *output, size_t *written)
933 {
934  error_t error;
935  uint_t i;
936  size_t n;
937  size_t length;
938  uint8_t *p;
939  Asn1Tag tag;
940 
941  //Initialize status code
942  error = NO_ERROR;
943 
944  //Point to the buffer where to write the ASN.1 structure
945  p = output;
946  //Length of the ASN.1 structure
947  length = 0;
948 
949  //The subject alternative name extension allows identities to be bound to the
950  //subject of the certificate. These identities may be included in addition
951  //to or in place of the identity in the subject field of the certificate
952  if(subjectAltName->numGeneralNames > 0)
953  {
954  //Format the extension identifier
955  tag.constructed = FALSE;
958  tag.length = sizeof(X509_SUBJECT_ALT_NAME_OID);
960 
961  //Write the corresponding ASN.1 tag
962  error = asn1WriteTag(&tag, FALSE, p, &n);
963  //Any error to report?
964  if(error)
965  return error;
966 
967  //Advance data pointer
968  ASN1_INC_POINTER(p, n);
969  //Total number of bytes that have been written
970  *written = n;
971 
972  //Loop through subject alternative names
973  for(i = 0; i < subjectAltName->numGeneralNames; i++)
974  {
975  //Format the current name
976  tag.constructed = FALSE;
978  tag.objType = subjectAltName->generalNames[i].type;
979  tag.length = subjectAltName->generalNames[i].length;
980  tag.value = (uint8_t *) subjectAltName->generalNames[i].value;
981 
982  //Write the corresponding ASN.1 tag
983  error = asn1WriteTag(&tag, FALSE, p, &n);
984  //Any error to report?
985  if(error)
986  return error;
987 
988  //Advance data pointer
989  ASN1_INC_POINTER(p, n);
990  length += n;
991  }
992 
993  //Point to the first object
994  if(output != NULL)
995  {
996  p = output + *written;
997  }
998  else
999  {
1000  p = NULL;
1001  }
1002 
1003  //The names are encapsulated within a sequence
1004  tag.constructed = TRUE;
1007  tag.length = length;
1008 
1009  //Write the corresponding ASN.1 tag
1010  error = asn1InsertHeader(&tag, p, &n);
1011  //Any error to report?
1012  if(error)
1013  return error;
1014 
1015  //Get the length of the resulting sequence
1016  length = tag.totalLength;
1017 
1018  //The extension value is encapsulated in an octet string
1019  tag.constructed = FALSE;
1022  tag.length = length;
1023 
1024  //Write the corresponding ASN.1 tag
1025  error = asn1InsertHeader(&tag, p, &n);
1026  //Any error to report?
1027  if(error)
1028  return error;
1029 
1030  //Adjust the length of the extension
1031  *written += tag.totalLength;
1032 
1033  //The extension is encapsulated within a sequence
1034  tag.constructed = TRUE;
1037  tag.length = *written;
1038 
1039  //Write the corresponding ASN.1 tag
1040  error = asn1InsertHeader(&tag, output, &n);
1041  //Any error to report?
1042  if(error)
1043  return error;
1044 
1045  //Get the length of the resulting tag
1046  length = tag.totalLength;
1047  }
1048 
1049  //Total number of bytes that have been written
1050  *written = length;
1051 
1052  //Successful processing
1053  return NO_ERROR;
1054 }
1055 
1056 
1057 /**
1058  * @brief Format SubjectKeyIdentifier extension
1059  * @param[in] subjectKeyId Value of the extension
1060  * @param[out] output Buffer where to format the ASN.1 structure
1061  * @param[out] written Length of the resulting ASN.1 structure
1062  * @return Error code
1063  **/
1064 
1066  uint8_t *output, size_t *written)
1067 {
1068  error_t error;
1069  size_t n;
1070  size_t length;
1071  uint8_t *p;
1072  Asn1Tag tag;
1073 
1074  //Initialize status code
1075  error = NO_ERROR;
1076 
1077  //Point to the buffer where to write the ASN.1 structure
1078  p = output;
1079  //Length of the ASN.1 structure
1080  length = 0;
1081 
1082  //The subject key identifier extension provides a means of identifying
1083  //certificates that contain a particular public key
1084  if(subjectKeyId->value != NULL && subjectKeyId->length > 0)
1085  {
1086  //Format the extension identifier
1087  tag.constructed = FALSE;
1090  tag.length = sizeof(X509_SUBJECT_KEY_ID_OID);
1092 
1093  //Write the corresponding ASN.1 tag
1094  error = asn1WriteTag(&tag, FALSE, p, &n);
1095  //Any error to report?
1096  if(error)
1097  return error;
1098 
1099  //Advance data pointer
1100  ASN1_INC_POINTER(p, n);
1101  length += n;
1102 
1103  //Format the KeyIdentifier field
1104  tag.constructed = FALSE;
1107  tag.length = subjectKeyId->length;
1108  tag.value = subjectKeyId->value;
1109 
1110  //Write the corresponding ASN.1 tag
1111  error = asn1WriteTag(&tag, FALSE, p, &n);
1112  //Any error to report?
1113  if(error)
1114  return error;
1115 
1116  //The extension value is encapsulated in an octet string
1117  tag.constructed = FALSE;
1120  tag.length = n;
1121 
1122  //Write the corresponding ASN.1 tag
1123  error = asn1InsertHeader(&tag, p, &n);
1124  //Any error to report?
1125  if(error)
1126  return error;
1127 
1128  //Adjust the length of the extension
1129  length += tag.totalLength;
1130 
1131  //The extension is encapsulated within a sequence
1132  tag.constructed = TRUE;
1135  tag.length = length;
1136 
1137  //Write the corresponding ASN.1 tag
1138  error = asn1InsertHeader(&tag, output, &n);
1139  //Any error to report?
1140  if(error)
1141  return error;
1142 
1143  //Get the length of the resulting sequence
1144  length = tag.totalLength;
1145  }
1146 
1147  //Total number of bytes that have been written
1148  *written = length;
1149 
1150  //Successful processing
1151  return NO_ERROR;
1152 }
1153 
1154 
1155 /**
1156  * @brief Format AuthorityKeyIdentifier extension
1157  * @param[in] authKeyId Value of the extension
1158  * @param[out] output Buffer where to format the ASN.1 structure
1159  * @param[out] written Length of the resulting ASN.1 structure
1160  * @return Error code
1161  **/
1162 
1164  uint8_t *output, size_t *written)
1165 {
1166  error_t error;
1167  size_t n;
1168  size_t length;
1169  uint8_t *p;
1170  Asn1Tag tag;
1171 
1172  //Initialize status code
1173  error = NO_ERROR;
1174 
1175  //Point to the buffer where to write the ASN.1 structure
1176  p = output;
1177  //Length of the ASN.1 structure
1178  length = 0;
1179 
1180  //The authority key identifier extension provides a means of identifying the
1181  //public key corresponding to the private key used to sign a certificate
1182  if(authKeyId->keyId.value != NULL && authKeyId->keyId.length > 0)
1183  {
1184  //Format the extension identifier
1185  tag.constructed = FALSE;
1188  tag.length = sizeof(X509_AUTHORITY_KEY_ID_OID);
1190 
1191  //Write the corresponding ASN.1 tag
1192  error = asn1WriteTag(&tag, FALSE, p, &n);
1193  //Any error to report?
1194  if(error)
1195  return error;
1196 
1197  //Advance data pointer
1198  ASN1_INC_POINTER(p, n);
1199  length += n;
1200 
1201  //Explicit tagging shall be used to encode the keyIdentifier field
1202  tag.constructed = FALSE;
1204  tag.objType = 0;
1205  tag.length = authKeyId->keyId.length;
1206  tag.value = authKeyId->keyId.value;
1207 
1208  //Write the corresponding ASN.1 tag
1209  error = asn1WriteTag(&tag, FALSE, p, &n);
1210  //Any error to report?
1211  if(error)
1212  return error;
1213 
1214  //The KeyIdentifier field is encapsulated within a sequence
1215  tag.constructed = TRUE;
1218  tag.length = n;
1219 
1220  //Write the corresponding ASN.1 tag
1221  error = asn1InsertHeader(&tag, p, &n);
1222  //Any error to report?
1223  if(error)
1224  return error;
1225 
1226  //Get the length of the resulting sequence
1227  n = tag.totalLength;
1228 
1229  //The extension value is encapsulated in an octet string
1230  tag.constructed = FALSE;
1233  tag.length = n;
1234 
1235  //Write the corresponding ASN.1 tag
1236  error = asn1InsertHeader(&tag, p, &n);
1237  //Any error to report?
1238  if(error)
1239  return error;
1240 
1241  //Adjust the length of the extension
1242  length += tag.totalLength;
1243 
1244  //The extension is encapsulated within a sequence
1245  tag.constructed = TRUE;
1248  tag.length = length;
1249 
1250  //Write the corresponding ASN.1 tag
1251  error = asn1InsertHeader(&tag, output, &n);
1252  //Any error to report?
1253  if(error)
1254  return error;
1255 
1256  //Get the length of the resulting sequence
1257  length = tag.totalLength;
1258  }
1259 
1260  //Total number of bytes that have been written
1261  *written = length;
1262 
1263  //Successful processing
1264  return NO_ERROR;
1265 }
1266 
1267 
1268 /**
1269  * @brief Format NetscapeCertType extension
1270  * @param[in] nsCertType Value of the extension
1271  * @param[out] output Buffer where to format the ASN.1 structure
1272  * @param[out] written Length of the resulting ASN.1 structure
1273  * @return Error code
1274  **/
1275 
1277  uint8_t *output, size_t *written)
1278 {
1279  error_t error;
1280  uint_t k;
1281  size_t n;
1282  size_t length;
1283  uint8_t *p;
1284  Asn1Tag tag;
1285  uint8_t buffer[2];
1286 
1287  //Initialize status code
1288  error = NO_ERROR;
1289 
1290  //Point to the buffer where to write the ASN.1 structure
1291  p = output;
1292  //Length of the ASN.1 structure
1293  length = 0;
1294 
1295  //The NetscapeCertType extension limit the use of a certificate
1296  if(nsCertType->bitmap != 0)
1297  {
1298  //Format the extension identifier
1299  tag.constructed = FALSE;
1302  tag.length = sizeof(X509_NS_CERT_TYPE_OID);
1304 
1305  //Write the corresponding ASN.1 tag
1306  error = asn1WriteTag(&tag, FALSE, p, &n);
1307  //Any error to report?
1308  if(error)
1309  return error;
1310 
1311  //Advance data pointer
1312  ASN1_INC_POINTER(p, n);
1313  length += n;
1314 
1315  //Calculate the length, in bits, of the NetscapeCertType value
1316  for(k = 8; k > 0; k--)
1317  {
1318  if(nsCertType->bitmap & (1U << (k - 1)))
1319  break;
1320  }
1321 
1322  //Encode bit string value
1323  buffer[0] = 8 - k;
1324  buffer[1] = reverseInt8(nsCertType->bitmap);
1325 
1326  //Format the bit string using ASN.1
1327  tag.constructed = FALSE;
1330  tag.length = sizeof(buffer);
1331  tag.value = buffer;
1332 
1333  //Write the corresponding ASN.1 tag
1334  error = asn1WriteTag(&tag, FALSE, p, &n);
1335  //Any error to report?
1336  if(error)
1337  return error;
1338 
1339  //The extension value is encapsulated in an octet string
1340  tag.constructed = FALSE;
1343  tag.length = n;
1344 
1345  //Write the corresponding ASN.1 tag
1346  error = asn1InsertHeader(&tag, p, &n);
1347  //Any error to report?
1348  if(error)
1349  return error;
1350 
1351  //Adjust the length of the extension
1352  length += tag.totalLength;
1353 
1354  //The extension is encapsulated within a sequence
1355  tag.constructed = TRUE;
1358  tag.length = length;
1359 
1360  //Write the corresponding ASN.1 tag
1361  error = asn1InsertHeader(&tag, output, &n);
1362  //Any error to report?
1363  if(error)
1364  return error;
1365 
1366  //Get the length of the resulting sequence
1367  length = tag.totalLength;
1368  }
1369 
1370  //Total number of bytes that have been written
1371  *written = length;
1372 
1373  //Successful processing
1374  return NO_ERROR;
1375 }
1376 
1377 #endif
@ X509_EXT_KEY_USAGE_ANY
Definition: x509_common.h:557
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:554
X509GeneralNameType type
Definition: x509_common.h:908
@ X509_EXT_KEY_USAGE_IPSEC_IKE
Definition: x509_common.h:553
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
error_t asn1InsertHeader(Asn1Tag *tag, uint8_t *data, size_t *written)
Insert an ASN.1 tag header.
Definition: asn1.c:643
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:550
@ X509_EXT_KEY_USAGE_CLIENT_AUTH
Definition: x509_common.h:545
@ X509_EXT_KEY_USAGE_SSH_SERVER
Definition: x509_common.h:555
@ X509_EXT_KEY_USAGE_IPSEC_END_SYSTEM
Definition: x509_common.h:548
const uint8_t X509_KP_OCSP_SIGNING_OID[8]
Definition: x509_common.c:146
Subject Key Identifier extension.
Definition: x509_common.h:932
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 totalLength
Definition: asn1.h:111
size_t length
Definition: asn1.h:109
#define FALSE
Definition: os_port.h:46
bool_t critical
Definition: x509_common.h:886
error_t
Error codes.
Definition: error.h:43
Extended Key Usage extension.
Definition: x509_common.h:896
#define ASN1_CLASS_UNIVERSAL
Definition: asn1.h:52
ASN.1 tag.
Definition: asn1.h:105
#define ASN1_INC_POINTER(p, n)
Definition: asn1.h:58
const uint8_t X509_KP_EMAIL_PROTECTION_OID[8]
Definition: x509_common.c:136
X.509 certificate extension.
Definition: x509_common.h:1039
const uint8_t X509_AUTHORITY_KEY_ID_OID[3]
Definition: x509_common.c:111
Authority Key Identifier extension.
Definition: x509_common.h:944
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:544
uint_t objClass
Definition: asn1.h:107
const uint8_t X509_KP_IPSEC_IKE_OID[8]
Definition: x509_common.c:148
uint8_t length
Definition: tcp.h:375
uint16_t bitmap
Definition: x509_common.h:887
const uint8_t X509_KP_CLIENT_AUTH_OID[8]
Definition: x509_common.c:132
Subject Alternative Name extension.
Definition: x509_common.h:919
@ X509_EXT_KEY_USAGE_DOC_SIGNING
Definition: x509_common.h:556
@ X509_EXT_KEY_USAGE_TIME_STAMPING
Definition: x509_common.h:551
Netscape certificate type.
Definition: x509_common.h:1028
@ X509_EXT_KEY_USAGE_IPSEC_TUNNEL
Definition: x509_common.h:549
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:909
@ ASN1_TYPE_OCTET_STRING
Definition: asn1.h:75
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:376
Basic Constraints extension.
Definition: x509_common.h:861
uint8_t reverseInt8(uint8_t value)
Reverse bit order in a byte.
Definition: cpu_endian.c:90
bool_t constructed
Definition: asn1.h:106
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:552
const uint8_t X509_KP_IPSEC_TUNNEL_OID[8]
Definition: x509_common.c:140
@ ASN1_TYPE_OBJECT_IDENTIFIER
Definition: asn1.h:77
@ ASN1_TYPE_SEQUENCE
Definition: asn1.h:83
X.509 certificate extensions.
Definition: x509_common.h:1051
X509OctetString oid
Definition: x509_common.h:1040
@ X509_EXT_KEY_USAGE_CODE_SIGNING
Definition: x509_common.h:546
const uint8_t X509_SUBJECT_KEY_ID_OID[3]
Definition: x509_common.c:81
const uint8_t * value
Definition: x509_common.h:702
const uint8_t * value
Definition: x509_common.h:934
const uint8_t X509_KP_IPSEC_END_SYSTEM_OID[8]
Definition: x509_common.c:138
@ ASN1_TYPE_BIT_STRING
Definition: asn1.h:74
X.509 extension formatting.
X509OctetString keyId
Definition: x509_common.h:946
unsigned int uint_t
Definition: compiler_port.h:57
error_t x509FormatNsCertType(const X509NsCertType *nsCertType, uint8_t *output, size_t *written)
Format NetscapeCertType extension.
X509OctetString data
Definition: x509_common.h:1042
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:781
@ ASN1_TYPE_BOOLEAN
Definition: asn1.h:72
@ X509_EXT_KEY_USAGE_EMAIL_PROTECTION
Definition: x509_common.h:547
X509GeneralName generalNames[X509_MAX_SUBJECT_ALT_NAMES]
Definition: x509_common.h:923
const uint8_t * value
Definition: asn1.h:110
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
uint_t objType
Definition: asn1.h:108
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:885