Browse Source

[crypto] Add functions for constructing ASN.1 objects

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 12 years ago
parent
commit
deac4ea1ba
2 changed files with 172 additions and 0 deletions
  1. 139
    0
      src/crypto/asn1.c
  2. 33
    0
      src/include/ipxe/asn1.h

+ 139
- 0
src/crypto/asn1.c View File

@@ -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
+}

+ 33
- 0
src/include/ipxe/asn1.h View File

@@ -21,6 +21,34 @@ struct asn1_cursor {
21 21
 	size_t len;
22 22
 };
23 23
 
24
+/** An ASN.1 object builder */
25
+struct asn1_builder {
26
+	/** Data
27
+	 *
28
+	 * This is always dynamically allocated.  If @c data is NULL
29
+	 * while @len is non-zero, this indicates that a memory
30
+	 * allocation error has occurred during the building process.
31
+	 */
32
+	void *data;
33
+	/** Length of data */
34
+	size_t len;
35
+};
36
+
37
+/** Maximum (viable) length of ASN.1 length
38
+ *
39
+ * While in theory unlimited, this length is sufficient to contain a
40
+ * size_t.
41
+ */
42
+#define ASN1_MAX_LEN_LEN ( 1 + sizeof ( size_t ) )
43
+
44
+/** An ASN.1 header */
45
+struct asn1_builder_header {
46
+	/** Type */
47
+	uint8_t type;
48
+	/** Length (encoded) */
49
+	uint8_t length[ASN1_MAX_LEN_LEN];
50
+} __attribute__ (( packed ));
51
+
24 52
 /** ASN.1 end */
25 53
 #define ASN1_END 0x00
26 54
 
@@ -255,5 +283,10 @@ extern int asn1_signature_algorithm ( const struct asn1_cursor *cursor,
255 283
 				      struct asn1_algorithm **algorithm );
256 284
 extern int asn1_generalized_time ( const struct asn1_cursor *cursor,
257 285
 				   time_t *time );
286
+extern int asn1_prepend_raw ( struct asn1_builder *builder, const void *data,
287
+			      size_t len );
288
+extern int asn1_prepend ( struct asn1_builder *builder, unsigned int type,
289
+			  const void *data, size_t len );
290
+extern int asn1_wrap ( struct asn1_builder *builder, unsigned int type );
258 291
 
259 292
 #endif /* _IPXE_ASN1_H */

Loading…
Cancel
Save