~ubuntu-branches/ubuntu/gutsy/wpasupplicant/gutsy

« back to all changes in this revision

Viewing changes to src/utils/base64.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2007-08-26 16:06:57 UTC
  • mto: This revision was merged to the branch mainline in revision 26.
  • Revision ID: james.westby@ubuntu.com-20070826160657-mxk5ivjjh65ptxlr
Tags: upstream-0.6.0+0.5.8
ImportĀ upstreamĀ versionĀ 0.6.0+0.5.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Base64 encoding/decoding (RFC1341)
3
 
 * Copyright (c) 2005, Jouni Malinen <j@w1.fi>
4
 
 *
5
 
 * This program is free software; you can redistribute it and/or modify
6
 
 * it under the terms of the GNU General Public License version 2 as
7
 
 * published by the Free Software Foundation.
8
 
 *
9
 
 * Alternatively, this software may be distributed under the terms of BSD
10
 
 * license.
11
 
 *
12
 
 * See README and COPYING for more details.
13
 
 */
14
 
 
15
 
#include "includes.h"
16
 
 
17
 
#include "os.h"
18
 
#include "base64.h"
19
 
 
20
 
static const unsigned char base64_table[65] =
21
 
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
22
 
 
23
 
/**
24
 
 * base64_encode - Base64 encode
25
 
 * @src: Data to be encoded
26
 
 * @len: Length of the data to be encoded
27
 
 * @out_len: Pointer to output length variable, or %NULL if not used
28
 
 * Returns: Allocated buffer of out_len bytes of encoded data,
29
 
 * or %NULL on failure
30
 
 *
31
 
 * Caller is responsible for freeing the returned buffer. Returned buffer is
32
 
 * nul terminated to make it easier to use as a C string. The nul terminator is
33
 
 * not included in out_len.
34
 
 */
35
 
unsigned char * base64_encode(const unsigned char *src, size_t len,
36
 
                              size_t *out_len)
37
 
{
38
 
        unsigned char *out, *pos;
39
 
        const unsigned char *end, *in;
40
 
        size_t olen;
41
 
        int line_len;
42
 
 
43
 
        olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */
44
 
        olen += olen / 72; /* line feeds */
45
 
        olen++; /* nul termination */
46
 
        out = os_malloc(olen);
47
 
        if (out == NULL)
48
 
                return NULL;
49
 
 
50
 
        end = src + len;
51
 
        in = src;
52
 
        pos = out;
53
 
        line_len = 0;
54
 
        while (end - in >= 3) {
55
 
                *pos++ = base64_table[in[0] >> 2];
56
 
                *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
57
 
                *pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)];
58
 
                *pos++ = base64_table[in[2] & 0x3f];
59
 
                in += 3;
60
 
                line_len += 4;
61
 
                if (line_len >= 72) {
62
 
                        *pos++ = '\n';
63
 
                        line_len = 0;
64
 
                }
65
 
        }
66
 
 
67
 
        if (end - in) {
68
 
                *pos++ = base64_table[in[0] >> 2];
69
 
                if (end - in == 1) {
70
 
                        *pos++ = base64_table[(in[0] & 0x03) << 4];
71
 
                        *pos++ = '=';
72
 
                } else {
73
 
                        *pos++ = base64_table[((in[0] & 0x03) << 4) |
74
 
                                              (in[1] >> 4)];
75
 
                        *pos++ = base64_table[(in[1] & 0x0f) << 2];
76
 
                }
77
 
                *pos++ = '=';
78
 
                line_len += 4;
79
 
        }
80
 
 
81
 
        if (line_len)
82
 
                *pos++ = '\n';
83
 
 
84
 
        *pos = '\0';
85
 
        if (out_len)
86
 
                *out_len = pos - out;
87
 
        return out;
88
 
}
89
 
 
90
 
 
91
 
/**
92
 
 * base64_decode - Base64 decode
93
 
 * @src: Data to be decoded
94
 
 * @len: Length of the data to be decoded
95
 
 * @out_len: Pointer to output length variable
96
 
 * Returns: Allocated buffer of out_len bytes of decoded data,
97
 
 * or %NULL on failure
98
 
 *
99
 
 * Caller is responsible for freeing the returned buffer.
100
 
 */
101
 
unsigned char * base64_decode(const unsigned char *src, size_t len,
102
 
                              size_t *out_len)
103
 
{
104
 
        unsigned char dtable[256], *out, *pos, in[4], block[4], tmp;
105
 
        size_t i, count, olen;
106
 
 
107
 
        os_memset(dtable, 0x80, 256);
108
 
        for (i = 0; i < sizeof(base64_table) - 1; i++)
109
 
                dtable[base64_table[i]] = (unsigned char) i;
110
 
        dtable['='] = 0;
111
 
 
112
 
        count = 0;
113
 
        for (i = 0; i < len; i++) {
114
 
                if (dtable[src[i]] != 0x80)
115
 
                        count++;
116
 
        }
117
 
 
118
 
        if (count % 4)
119
 
                return NULL;
120
 
 
121
 
        olen = count / 4 * 3;
122
 
        pos = out = os_malloc(olen);
123
 
        if (out == NULL)
124
 
                return NULL;
125
 
 
126
 
        count = 0;
127
 
        for (i = 0; i < len; i++) {
128
 
                tmp = dtable[src[i]];
129
 
                if (tmp == 0x80)
130
 
                        continue;
131
 
 
132
 
                in[count] = src[i];
133
 
                block[count] = tmp;
134
 
                count++;
135
 
                if (count == 4) {
136
 
                        *pos++ = (block[0] << 2) | (block[1] >> 4);
137
 
                        *pos++ = (block[1] << 4) | (block[2] >> 2);
138
 
                        *pos++ = (block[2] << 6) | block[3];
139
 
                        count = 0;
140
 
                }
141
 
        }
142
 
 
143
 
        if (pos > out) {
144
 
                if (in[2] == '=')
145
 
                        pos -= 2;
146
 
                else if (in[3] == '=')
147
 
                        pos--;
148
 
        }
149
 
 
150
 
        *out_len = pos - out;
151
 
        return out;
152
 
}
153
 
 
154
 
 
155
 
#ifdef TEST_MAIN
156
 
 
157
 
int main(int argc, char *argv[])
158
 
{
159
 
        FILE *f;
160
 
        size_t len, elen;
161
 
        unsigned char *buf, *e;
162
 
 
163
 
        if (argc != 4) {
164
 
                printf("Usage: base64 <encode|decode> <in file> <out file>\n");
165
 
                return -1;
166
 
        }
167
 
 
168
 
        buf = os_readfile(argv[2], &len);
169
 
        if (buf == NULL)
170
 
                return -1;
171
 
 
172
 
        if (strcmp(argv[1], "encode") == 0)
173
 
                e = base64_encode(buf, len, &elen);
174
 
        else
175
 
                e = base64_decode(buf, len, &elen);
176
 
        if (e == NULL)
177
 
                return -2;
178
 
        f = fopen(argv[3], "w");
179
 
        if (f == NULL)
180
 
                return -3;
181
 
        fwrite(e, 1, elen, f);
182
 
        fclose(f);
183
 
        free(e);
184
 
 
185
 
        return 0;
186
 
}
187
 
#endif /* TEST_MAIN */