|
@@ -20,6 +20,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
20
|
20
|
|
21
|
21
|
#include <stdint.h>
|
22
|
22
|
#include <stddef.h>
|
|
23
|
+#include <stdlib.h>
|
23
|
24
|
#include <string.h>
|
24
|
25
|
#include <ctype.h>
|
25
|
26
|
#include <errno.h>
|
|
@@ -699,3 +700,141 @@ int asn1_generalized_time ( const struct asn1_cursor *cursor, time_t *time ) {
|
699
|
700
|
|
700
|
701
|
return 0;
|
701
|
702
|
}
|
|
703
|
+
|
|
704
|
+/**
|
|
705
|
+ * Construct ASN.1 header
|
|
706
|
+ *
|
|
707
|
+ * @v header ASN.1 builder header
|
|
708
|
+ * @v type Type
|
|
709
|
+ * @v len Content length
|
|
710
|
+ * @ret header_len Header length
|
|
711
|
+ */
|
|
712
|
+static size_t asn1_header ( struct asn1_builder_header *header,
|
|
713
|
+ unsigned int type, size_t len ) {
|
|
714
|
+ unsigned int header_len = 2;
|
|
715
|
+ unsigned int len_len = 0;
|
|
716
|
+ size_t temp;
|
|
717
|
+
|
|
718
|
+ /* Construct header */
|
|
719
|
+ header->type = type;
|
|
720
|
+ if ( len < 0x80 ) {
|
|
721
|
+ header->length[0] = len;
|
|
722
|
+ } else {
|
|
723
|
+ for ( temp = len ; temp ; temp >>= 8 )
|
|
724
|
+ len_len++;
|
|
725
|
+ header->length[0] = ( 0x80 | len_len );
|
|
726
|
+ header_len += len_len;
|
|
727
|
+ for ( temp = len ; temp ; temp >>= 8 )
|
|
728
|
+ header->length[len_len--] = ( temp & 0xff );
|
|
729
|
+ }
|
|
730
|
+
|
|
731
|
+ return header_len;
|
|
732
|
+}
|
|
733
|
+
|
|
734
|
+/**
|
|
735
|
+ * Grow ASN.1 builder
|
|
736
|
+ *
|
|
737
|
+ * @v builder ASN.1 builder
|
|
738
|
+ * @v extra Extra space to prepend
|
|
739
|
+ * @ret rc Return status code
|
|
740
|
+ */
|
|
741
|
+static int asn1_grow ( struct asn1_builder *builder, size_t extra ) {
|
|
742
|
+ size_t new_len;
|
|
743
|
+ void *new;
|
|
744
|
+
|
|
745
|
+ /* As with the ASN1 parsing functions, make errors permanent */
|
|
746
|
+ if ( builder->len && ! builder->data )
|
|
747
|
+ return -ENOMEM;
|
|
748
|
+
|
|
749
|
+ /* Reallocate data buffer */
|
|
750
|
+ new_len = ( builder->len + extra );
|
|
751
|
+ new = realloc ( builder->data, new_len );
|
|
752
|
+ if ( ! new ) {
|
|
753
|
+ free ( builder->data );
|
|
754
|
+ builder->data = NULL;
|
|
755
|
+ return -ENOMEM;
|
|
756
|
+ }
|
|
757
|
+ builder->data = new;
|
|
758
|
+
|
|
759
|
+ /* Move existing data to end of buffer */
|
|
760
|
+ memmove ( ( builder->data + extra ), builder->data, builder->len );
|
|
761
|
+ builder->len = new_len;
|
|
762
|
+
|
|
763
|
+ return 0;
|
|
764
|
+}
|
|
765
|
+
|
|
766
|
+/**
|
|
767
|
+ * Prepend raw data to ASN.1 builder
|
|
768
|
+ *
|
|
769
|
+ * @v builder ASN.1 builder
|
|
770
|
+ * @v data Data to prepend
|
|
771
|
+ * @v len Length of data to prepend
|
|
772
|
+ * @ret rc Return status code
|
|
773
|
+ */
|
|
774
|
+int asn1_prepend_raw ( struct asn1_builder *builder, const void *data,
|
|
775
|
+ size_t len ) {
|
|
776
|
+ int rc;
|
|
777
|
+
|
|
778
|
+ /* Grow buffer */
|
|
779
|
+ if ( ( rc = asn1_grow ( builder, len ) ) != 0 )
|
|
780
|
+ return rc;
|
|
781
|
+
|
|
782
|
+ /* Populate data buffer */
|
|
783
|
+ memcpy ( builder->data, data, len );
|
|
784
|
+
|
|
785
|
+ return 0;
|
|
786
|
+}
|
|
787
|
+
|
|
788
|
+/**
|
|
789
|
+ * Prepend data to ASN.1 builder
|
|
790
|
+ *
|
|
791
|
+ * @v builder ASN.1 builder
|
|
792
|
+ * @v type Type
|
|
793
|
+ * @v data Data to prepend
|
|
794
|
+ * @v len Length of data to prepend
|
|
795
|
+ * @ret rc Return status code
|
|
796
|
+ */
|
|
797
|
+int asn1_prepend ( struct asn1_builder *builder, unsigned int type,
|
|
798
|
+ const void *data, size_t len ) {
|
|
799
|
+ struct asn1_builder_header header;
|
|
800
|
+ size_t header_len;
|
|
801
|
+ int rc;
|
|
802
|
+
|
|
803
|
+ /* Construct header */
|
|
804
|
+ header_len = asn1_header ( &header, type, len );
|
|
805
|
+
|
|
806
|
+ /* Grow buffer */
|
|
807
|
+ if ( ( rc = asn1_grow ( builder, header_len + len ) ) != 0 )
|
|
808
|
+ return rc;
|
|
809
|
+
|
|
810
|
+ /* Populate data buffer */
|
|
811
|
+ memcpy ( builder->data, &header, header_len );
|
|
812
|
+ memcpy ( ( builder->data + header_len ), data, len );
|
|
813
|
+
|
|
814
|
+ return 0;
|
|
815
|
+}
|
|
816
|
+
|
|
817
|
+/**
|
|
818
|
+ * Wrap ASN.1 builder
|
|
819
|
+ *
|
|
820
|
+ * @v builder ASN.1 builder
|
|
821
|
+ * @v type Type
|
|
822
|
+ * @ret rc Return status code
|
|
823
|
+ */
|
|
824
|
+int asn1_wrap ( struct asn1_builder *builder, unsigned int type ) {
|
|
825
|
+ struct asn1_builder_header header;
|
|
826
|
+ size_t header_len;
|
|
827
|
+ int rc;
|
|
828
|
+
|
|
829
|
+ /* Construct header */
|
|
830
|
+ header_len = asn1_header ( &header, type, builder->len );
|
|
831
|
+
|
|
832
|
+ /* Grow buffer */
|
|
833
|
+ if ( ( rc = asn1_grow ( builder, header_len ) ) != 0 )
|
|
834
|
+ return rc;
|
|
835
|
+
|
|
836
|
+ /* Populate data buffer */
|
|
837
|
+ memcpy ( builder->data, &header, header_len );
|
|
838
|
+
|
|
839
|
+ return 0;
|
|
840
|
+}
|