|
@@ -43,80 +43,73 @@ static const char base64[64] =
|
43
|
43
|
* Base64-encode data
|
44
|
44
|
*
|
45
|
45
|
* @v raw Raw data
|
46
|
|
- * @v len Length of raw data
|
47
|
|
- * @v encoded Buffer for encoded string
|
48
|
|
- *
|
49
|
|
- * The buffer must be the correct length for the encoded string. Use
|
50
|
|
- * something like
|
51
|
|
- *
|
52
|
|
- * char buf[ base64_encoded_len ( len ) + 1 ];
|
53
|
|
- *
|
54
|
|
- * (the +1 is for the terminating NUL) to provide a buffer of the
|
55
|
|
- * correct size.
|
|
46
|
+ * @v raw_len Length of raw data
|
|
47
|
+ * @v data Buffer
|
|
48
|
+ * @v len Length of buffer
|
|
49
|
+ * @ret len Encoded length
|
56
|
50
|
*/
|
57
|
|
-void base64_encode ( const uint8_t *raw, size_t len, char *encoded ) {
|
|
51
|
+size_t base64_encode ( const void *raw, size_t raw_len, char *data,
|
|
52
|
+ size_t len ) {
|
58
|
53
|
const uint8_t *raw_bytes = ( ( const uint8_t * ) raw );
|
59
|
|
- uint8_t *encoded_bytes = ( ( uint8_t * ) encoded );
|
60
|
|
- size_t raw_bit_len = ( 8 * len );
|
|
54
|
+ size_t raw_bit_len = ( 8 * raw_len );
|
|
55
|
+ size_t used = 0;
|
61
|
56
|
unsigned int bit;
|
62
|
57
|
unsigned int byte;
|
63
|
58
|
unsigned int shift;
|
64
|
59
|
unsigned int tmp;
|
65
|
60
|
|
66
|
|
- for ( bit = 0 ; bit < raw_bit_len ; bit += 6 ) {
|
|
61
|
+ for ( bit = 0 ; bit < raw_bit_len ; bit += 6, used++ ) {
|
67
|
62
|
byte = ( bit / 8 );
|
68
|
63
|
shift = ( bit % 8 );
|
69
|
64
|
tmp = ( raw_bytes[byte] << shift );
|
70
|
|
- if ( ( byte + 1 ) < len )
|
|
65
|
+ if ( ( byte + 1 ) < raw_len )
|
71
|
66
|
tmp |= ( raw_bytes[ byte + 1 ] >> ( 8 - shift ) );
|
72
|
67
|
tmp = ( ( tmp >> 2 ) & 0x3f );
|
73
|
|
- *(encoded_bytes++) = base64[tmp];
|
|
68
|
+ if ( used < len )
|
|
69
|
+ data[used] = base64[tmp];
|
74
|
70
|
}
|
75
|
|
- for ( ; ( bit % 8 ) != 0 ; bit += 6 )
|
76
|
|
- *(encoded_bytes++) = '=';
|
77
|
|
- *(encoded_bytes++) = '\0';
|
|
71
|
+ for ( ; ( bit % 8 ) != 0 ; bit += 6, used++ ) {
|
|
72
|
+ if ( used < len )
|
|
73
|
+ data[used] = '=';
|
|
74
|
+ }
|
|
75
|
+ if ( used < len )
|
|
76
|
+ data[used] = '\0';
|
|
77
|
+ if ( len )
|
|
78
|
+ data[ len - 1 ] = '\0'; /* Ensure terminator exists */
|
78
|
79
|
|
79
|
|
- DBG ( "Base64-encoded to \"%s\":\n", encoded );
|
80
|
|
- DBG_HDA ( 0, raw, len );
|
81
|
|
- assert ( strlen ( encoded ) == base64_encoded_len ( len ) );
|
|
80
|
+ return used;
|
82
|
81
|
}
|
83
|
82
|
|
84
|
83
|
/**
|
85
|
84
|
* Base64-decode string
|
86
|
85
|
*
|
87
|
86
|
* @v encoded Encoded string
|
88
|
|
- * @v raw Raw data
|
89
|
|
- * @ret len Length of raw data, or negative error
|
90
|
|
- *
|
91
|
|
- * The buffer must be large enough to contain the decoded data. Use
|
92
|
|
- * something like
|
93
|
|
- *
|
94
|
|
- * char buf[ base64_decoded_max_len ( encoded ) ];
|
95
|
|
- *
|
96
|
|
- * to provide a buffer of the correct size.
|
|
87
|
+ * @v data Buffer
|
|
88
|
+ * @v len Length of buffer
|
|
89
|
+ * @ret len Length of data, or negative error
|
97
|
90
|
*/
|
98
|
|
-int base64_decode ( const char *encoded, uint8_t *raw ) {
|
99
|
|
- const uint8_t *encoded_bytes = ( ( const uint8_t * ) encoded );
|
100
|
|
- uint8_t *raw_bytes = ( ( uint8_t * ) raw );
|
101
|
|
- uint8_t encoded_byte;
|
|
91
|
+int base64_decode ( const char *encoded, void *data, size_t len ) {
|
|
92
|
+ const char *in = encoded;
|
|
93
|
+ uint8_t *out = data;
|
|
94
|
+ uint8_t in_char;
|
102
|
95
|
char *match;
|
103
|
|
- int decoded;
|
|
96
|
+ int in_bits;
|
104
|
97
|
unsigned int bit = 0;
|
105
|
98
|
unsigned int pad_count = 0;
|
106
|
|
- size_t len;
|
|
99
|
+ size_t offset;
|
107
|
100
|
|
108
|
|
- /* Zero the raw data */
|
109
|
|
- memset ( raw, 0, base64_decoded_max_len ( encoded ) );
|
|
101
|
+ /* Zero the output buffer */
|
|
102
|
+ memset ( data, 0, len );
|
110
|
103
|
|
111
|
104
|
/* Decode string */
|
112
|
|
- while ( ( encoded_byte = *(encoded_bytes++) ) ) {
|
|
105
|
+ while ( ( in_char = *(in++) ) ) {
|
113
|
106
|
|
114
|
107
|
/* Ignore whitespace characters */
|
115
|
|
- if ( isspace ( encoded_byte ) )
|
|
108
|
+ if ( isspace ( in_char ) )
|
116
|
109
|
continue;
|
117
|
110
|
|
118
|
111
|
/* Process pad characters */
|
119
|
|
- if ( encoded_byte == '=' ) {
|
|
112
|
+ if ( in_char == '=' ) {
|
120
|
113
|
if ( pad_count >= 2 ) {
|
121
|
114
|
DBG ( "Base64-encoded string \"%s\" has too "
|
122
|
115
|
"many pad characters\n", encoded );
|
|
@@ -133,18 +126,22 @@ int base64_decode ( const char *encoded, uint8_t *raw ) {
|
133
|
126
|
}
|
134
|
127
|
|
135
|
128
|
/* Process normal characters */
|
136
|
|
- match = strchr ( base64, encoded_byte );
|
|
129
|
+ match = strchr ( base64, in_char );
|
137
|
130
|
if ( ! match ) {
|
138
|
131
|
DBG ( "Base64-encoded string \"%s\" contains invalid "
|
139
|
|
- "character '%c'\n", encoded, encoded_byte );
|
|
132
|
+ "character '%c'\n", encoded, in_char );
|
140
|
133
|
return -EINVAL;
|
141
|
134
|
}
|
142
|
|
- decoded = ( match - base64 );
|
|
135
|
+ in_bits = ( match - base64 );
|
143
|
136
|
|
144
|
137
|
/* Add to raw data */
|
145
|
|
- decoded <<= 2;
|
146
|
|
- raw_bytes[ bit / 8 ] |= ( decoded >> ( bit % 8 ) );
|
147
|
|
- raw_bytes[ bit / 8 + 1 ] |= ( decoded << ( 8 - ( bit % 8 ) ) );
|
|
138
|
+ in_bits <<= 2;
|
|
139
|
+ offset = ( bit / 8 );
|
|
140
|
+ if ( offset < len )
|
|
141
|
+ out[offset] |= ( in_bits >> ( bit % 8 ) );
|
|
142
|
+ offset++;
|
|
143
|
+ if ( offset < len )
|
|
144
|
+ out[offset] |= ( in_bits << ( 8 - ( bit % 8 ) ) );
|
148
|
145
|
bit += 6;
|
149
|
146
|
}
|
150
|
147
|
|
|
@@ -154,12 +151,7 @@ int base64_decode ( const char *encoded, uint8_t *raw ) {
|
154
|
151
|
"%d\n", encoded, bit );
|
155
|
152
|
return -EINVAL;
|
156
|
153
|
}
|
157
|
|
- len = ( bit / 8 );
|
158
|
|
-
|
159
|
|
- DBG ( "Base64-decoded \"%s\" to:\n", encoded );
|
160
|
|
- DBG_HDA ( 0, raw, len );
|
161
|
|
- assert ( len <= base64_decoded_max_len ( encoded ) );
|
162
|
154
|
|
163
|
155
|
/* Return length in bytes */
|
164
|
|
- return ( len );
|
|
156
|
+ return ( bit / 8 );
|
165
|
157
|
}
|