Преглед изворни кода

[base64] Add ability to decode base64 strings

Inspired-by: Piotr Jaroszyński <p.jaroszynski@gmail.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown пре 14 година
родитељ
комит
97ea628484
3 измењених фајлова са 101 додато и 0 уклоњено
  1. 85
    0
      src/core/base64.c
  2. 15
    0
      src/include/ipxe/base64.h
  3. 1
    0
      src/include/ipxe/errfile.h

+ 85
- 0
src/core/base64.c Прегледај датотеку

@@ -20,6 +20,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
20 20
 
21 21
 #include <stdint.h>
22 22
 #include <string.h>
23
+#include <ctype.h>
24
+#include <errno.h>
23 25
 #include <assert.h>
24 26
 #include <ipxe/base64.h>
25 27
 
@@ -68,3 +70,86 @@ void base64_encode ( const uint8_t *raw, size_t len, char *encoded ) {
68 70
 	DBG_HDA ( 0, raw, len );
69 71
 	assert ( strlen ( encoded ) == base64_encoded_len ( len ) );
70 72
 }
73
+
74
+/**
75
+ * Base64-decode string
76
+ *
77
+ * @v encoded		Encoded string
78
+ * @v raw		Raw data
79
+ * @ret len		Length of raw data, or negative error
80
+ *
81
+ * The buffer must be large enough to contain the decoded data.  Use
82
+ * something like
83
+ *
84
+ *     char buf[ base64_decoded_max_len ( encoded ) ];
85
+ *
86
+ * to provide a buffer of the correct size.
87
+ */
88
+int base64_decode ( const char *encoded, uint8_t *raw ) {
89
+	const uint8_t *encoded_bytes = ( ( const uint8_t * ) encoded );
90
+	uint8_t *raw_bytes = ( ( uint8_t * ) raw );
91
+	uint8_t encoded_byte;
92
+	char *match;
93
+	int decoded;
94
+	unsigned int bit = 0;
95
+	unsigned int pad_count = 0;
96
+	size_t len;
97
+
98
+	/* Zero the raw data */
99
+	memset ( raw, 0, base64_decoded_max_len ( encoded ) );
100
+
101
+	/* Decode string */
102
+	while ( ( encoded_byte = *(encoded_bytes++) ) ) {
103
+
104
+		/* Ignore whitespace characters */
105
+		if ( isspace ( encoded_byte ) )
106
+			continue;
107
+
108
+		/* Process pad characters */
109
+		if ( encoded_byte == '=' ) {
110
+			if ( pad_count >= 2 ) {
111
+				DBG ( "Base64-encoded string \"%s\" has too "
112
+				      "many pad characters\n", encoded );
113
+				return -EINVAL;
114
+			}
115
+			pad_count++;
116
+			bit -= 2; /* unused_bits = ( 2 * pad_count ) */
117
+			continue;
118
+		}
119
+		if ( pad_count ) {
120
+			DBG ( "Base64-encoded string \"%s\" has invalid pad "
121
+			      "sequence\n", encoded );
122
+			return -EINVAL;
123
+		}
124
+
125
+		/* Process normal characters */
126
+		match = strchr ( base64, encoded_byte );
127
+		if ( ! match ) {
128
+			DBG ( "Base64-encoded string \"%s\" contains invalid "
129
+			      "character '%c'\n", encoded, encoded_byte );
130
+			return -EINVAL;
131
+		}
132
+		decoded = ( match - base64 );
133
+
134
+		/* Add to raw data */
135
+		decoded <<= 2;
136
+		raw_bytes[ bit / 8 ] |= ( decoded >> ( bit % 8 ) );
137
+		raw_bytes[ bit / 8 + 1 ] |= ( decoded << ( 8 - ( bit % 8 ) ) );
138
+		bit += 6;
139
+	}
140
+
141
+	/* Check that we decoded a whole number of bytes */
142
+	if ( ( bit % 8 ) != 0 ) {
143
+		DBG ( "Base64-encoded string \"%s\" has invalid bit length "
144
+		      "%d\n", encoded, bit );
145
+		return -EINVAL;
146
+	}
147
+	len = ( bit / 8 );
148
+
149
+	DBG ( "Base64-decoded \"%s\" to:\n", encoded );
150
+	DBG_HDA ( 0, raw, len );
151
+	assert ( len <= base64_decoded_max_len ( encoded ) );
152
+
153
+	/* Return length in bytes */
154
+	return ( len );
155
+}

+ 15
- 0
src/include/ipxe/base64.h Прегледај датотеку

@@ -10,6 +10,7 @@
10 10
 FILE_LICENCE ( GPL2_OR_LATER );
11 11
 
12 12
 #include <stdint.h>
13
+#include <string.h>
13 14
 
14 15
 /**
15 16
  * Calculate length of base64-encoded data
@@ -21,6 +22,20 @@ static inline size_t base64_encoded_len ( size_t raw_len ) {
21 22
 	return ( ( ( raw_len + 3 - 1 ) / 3 ) * 4 );
22 23
 }
23 24
 
25
+/**
26
+ * Calculate maximum length of base64-decoded string
27
+ *
28
+ * @v encoded		Encoded string
29
+ * @v max_raw_len	Maximum length of raw data
30
+ *
31
+ * Note that the exact length of the raw data cannot be known until
32
+ * the string is decoded.
33
+ */
34
+static inline size_t base64_decoded_max_len ( const char *encoded ) {
35
+	return ( ( ( strlen ( encoded ) + 4 - 1 ) / 4 ) * 3 );
36
+}
37
+
24 38
 extern void base64_encode ( const uint8_t *raw, size_t len, char *encoded );
39
+extern int base64_decode ( const char *encoded, uint8_t *raw );
25 40
 
26 41
 #endif /* _IPXE_BASE64_H */

+ 1
- 0
src/include/ipxe/errfile.h Прегледај датотеку

@@ -53,6 +53,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
53 53
 #define ERRFILE_vsprintf	       ( ERRFILE_CORE | 0x000d0000 )
54 54
 #define ERRFILE_xfer		       ( ERRFILE_CORE | 0x000e0000 )
55 55
 #define ERRFILE_bitmap		       ( ERRFILE_CORE | 0x000f0000 )
56
+#define ERRFILE_base64		       ( ERRFILE_CORE | 0x00100000 )
56 57
 
57 58
 #define ERRFILE_eisa		     ( ERRFILE_DRIVER | 0x00000000 )
58 59
 #define ERRFILE_isa		     ( ERRFILE_DRIVER | 0x00010000 )

Loading…
Откажи
Сачувај