iPXE
base64.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27#include <stdint.h>
28#include <string.h>
29#include <ctype.h>
30#include <errno.h>
31#include <assert.h>
32#include <ipxe/base64.h>
33
34/** @file
35 *
36 * Base64 encoding
37 *
38 */
39
40static const char base64[ 64 + 1 /* NUL */ ] =
41 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
42
43/**
44 * Base64-encode data
45 *
46 * @v raw Raw data
47 * @v raw_len Length of raw data
48 * @v data Buffer
49 * @v len Length of buffer
50 * @ret len Encoded length
51 */
52size_t base64_encode ( const void *raw, size_t raw_len, char *data,
53 size_t len ) {
54 const uint8_t *raw_bytes = ( ( const uint8_t * ) raw );
55 size_t raw_bit_len = ( 8 * raw_len );
56 size_t used = 0;
57 unsigned int bit;
58 unsigned int byte;
59 unsigned int shift;
60 unsigned int tmp;
61
62 for ( bit = 0 ; bit < raw_bit_len ; bit += 6, used++ ) {
63 byte = ( bit / 8 );
64 shift = ( bit % 8 );
65 tmp = ( raw_bytes[byte] << shift );
66 if ( ( byte + 1 ) < raw_len )
67 tmp |= ( raw_bytes[ byte + 1 ] >> ( 8 - shift ) );
68 tmp = ( ( tmp >> 2 ) & 0x3f );
69 if ( used < len )
70 data[used] = base64[tmp];
71 }
72 for ( ; ( bit % 8 ) != 0 ; bit += 6, used++ ) {
73 if ( used < len )
74 data[used] = '=';
75 }
76 if ( used < len )
77 data[used] = '\0';
78 if ( len )
79 data[ len - 1 ] = '\0'; /* Ensure terminator exists */
80
81 return used;
82}
83
84/**
85 * Base64-decode string
86 *
87 * @v encoded Encoded string
88 * @v data Buffer
89 * @v len Length of buffer
90 * @ret len Length of data, or negative error
91 */
92int base64_decode ( const char *encoded, void *data, size_t len ) {
93 const char *in = encoded;
94 uint8_t *out = data;
95 uint8_t in_char;
96 char *match;
97 int in_bits;
98 unsigned int bit = 0;
99 unsigned int pad_count = 0;
100 size_t offset;
101
102 /* Zero the output buffer */
103 memset ( data, 0, len );
104
105 /* Decode string */
106 while ( ( in_char = *(in++) ) ) {
107
108 /* Ignore whitespace characters */
109 if ( isspace ( in_char ) )
110 continue;
111
112 /* Process pad characters */
113 if ( in_char == '=' ) {
114 if ( pad_count >= 2 ) {
115 DBG ( "Base64-encoded string \"%s\" has too "
116 "many pad characters\n", encoded );
117 return -EINVAL;
118 }
119 pad_count++;
120 bit -= 2; /* unused_bits = ( 2 * pad_count ) */
121 continue;
122 }
123 if ( pad_count ) {
124 DBG ( "Base64-encoded string \"%s\" has invalid pad "
125 "sequence\n", encoded );
126 return -EINVAL;
127 }
128
129 /* Process normal characters */
130 match = strchr ( base64, in_char );
131 if ( ! match ) {
132 DBG ( "Base64-encoded string \"%s\" contains invalid "
133 "character '%c'\n", encoded, in_char );
134 return -EINVAL;
135 }
136 in_bits = ( match - base64 );
137
138 /* Add to raw data */
139 in_bits <<= 2;
140 offset = ( bit / 8 );
141 if ( offset < len )
142 out[offset] |= ( in_bits >> ( bit % 8 ) );
143 offset++;
144 if ( offset < len )
145 out[offset] |= ( in_bits << ( 8 - ( bit % 8 ) ) );
146 bit += 6;
147 }
148
149 /* Check that we decoded a whole number of bytes */
150 if ( ( bit % 8 ) != 0 ) {
151 DBG ( "Base64-encoded string \"%s\" has invalid bit length "
152 "%d\n", encoded, bit );
153 return -EINVAL;
154 }
155
156 /* Return length in bytes */
157 return ( bit / 8 );
158}
__be32 raw[7]
Definition CIB_PRM.h:0
__be32 in[4]
Definition CIB_PRM.h:7
__be32 out[4]
Definition CIB_PRM.h:8
unsigned char uint8_t
Definition stdint.h:10
Assertions.
static size_t raw_len
Definition base16.h:54
size_t base64_encode(const void *raw, size_t raw_len, char *data, size_t len)
Base64-encode data.
Definition base64.c:52
int base64_decode(const char *encoded, void *data, size_t len)
Base64-decode string.
Definition base64.c:92
static const char base64[64+1]
Definition base64.c:40
Base64 encoding.
uint16_t offset
Offset to command line.
Definition bzimage.h:3
int isspace(int character)
Check to see if character is a space.
Definition ctype.c:42
Character types.
ring len
Length.
Definition dwmac.h:226
uint8_t data[48]
Additional event data.
Definition ena.h:11
Error codes.
#define DBG(...)
Print a debugging message.
Definition compiler.h:498
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define EINVAL
Invalid argument.
Definition errno.h:429
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
static unsigned int unsigned int bit
Definition bigint.h:392
String functions.
void * memset(void *dest, int character, size_t len) __nonnull
unsigned long tmp
Definition linux_pci.h:65
unsigned char byte
Definition smc9000.h:38
char * strchr(const char *src, int character)
Find character within a string.
Definition string.c:272