root/trunk/src/libopensc/base64.c

Revision 3084, 4.0 KB (checked in by aj, 2 years ago)

convert to utf-8.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * base64.c: Base64 converting functions
3 *
4 * Copyright (C) 2001, 2002  Juha YrjölÀ <juha.yrjola@iki.fi>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21#include "internal.h"
22#include <stdlib.h>
23#include <string.h>
24#include <stdio.h>
25#include <assert.h>
26
27static const u8 base64_table[66] =
28        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
29        "0123456789+/=";
30
31static const u8 bin_table[128] = {
32        0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
33        0xFF,0xE0,0xD0,0xFF,0xFF,0xD0,0xFF,0xFF,
34        0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
35        0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
36        0xE0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
37        0xFF,0xFF,0xFF,0x3E,0xFF,0xF2,0xFF,0x3F,
38        0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,
39        0x3C,0x3D,0xFF,0xFF,0xFF,0xC0,0xFF,0xFF,
40        0xFF,0x00,0x01,0x02,0x03,0x04,0x05,0x06,
41        0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,
42        0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,
43        0x17,0x18,0x19,0xFF,0xFF,0xFF,0xFF,0xFF,
44        0xFF,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,
45        0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,
46        0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,
47        0x31,0x32,0x33,0xFF,0xFF,0xFF,0xFF,0xFF,
48};
49
50static void to_base64(unsigned int i, u8 *out, unsigned int fillers)
51{
52        unsigned int s = 18, c;
53       
54        for (c = 0; c < 4; c++) {
55                if (fillers >= 4 - c)
56                        *out = base64_table[64];
57                else
58                        *out = base64_table[(i >> s) & 0x3f];
59                out++;
60                s -= 6;
61        }
62}
63
64static int from_base64(const char *in, unsigned int *out, int *skip)
65{
66        unsigned int res = 0, c, s = 18;
67        const char *in0 = in;
68       
69        for (c = 0; c < 4; c++, in++) {
70                u8 b;
71                int k = *in;
72               
73                if (k < 0)
74                        return -1;
75                if (k == 0 && c == 0)
76                        return 0;
77                b = bin_table[k];
78                if (b == 0xC0) /* '=' */
79                        break;
80                switch (b) {
81                case 0xD0: /* '\n' or '\r' */
82                        c--;
83                        continue;
84                }
85                if (b > 0x3f)
86                        return -1;
87
88                res |= b << s;
89                s -= 6;
90        }
91        *skip = in - in0;
92        *out = res;
93        return c * 6 / 8;
94}
95
96int sc_base64_encode(const u8 *in, size_t len, u8 *out, size_t outlen, size_t linelength)
97{
98        unsigned int chars = 0;
99        size_t i, c;
100
101        linelength -= linelength & 0x03;
102        while (len >= 3) {
103                i = in[2] + (in[1] << 8) + (in[0] << 16);
104                in += 3;
105                len -= 3;
106                if (outlen < 4)
107                        return SC_ERROR_BUFFER_TOO_SMALL;
108                to_base64(i, out, 0);
109                out += 4;
110                outlen -= 4;
111                chars += 4;
112                if (chars >= linelength && linelength > 0) {
113                        if (outlen < 1)
114                                return SC_ERROR_BUFFER_TOO_SMALL;
115                        *out = '\n';
116                        out++;
117                        outlen--;
118                        chars = 0;
119                }
120        }
121        i = c = 0;
122        while (c < len)
123                i |= *in++ << ((2 - c++) << 3);
124        if (len) {
125                if (outlen < 4)
126                        return SC_ERROR_BUFFER_TOO_SMALL;
127                to_base64(i, out, 3-len);
128                out += 4;
129                outlen -= 4;
130                chars += 4;
131        }
132        if (chars && linelength > 0) {
133                if (outlen < 1)
134                        return SC_ERROR_BUFFER_TOO_SMALL;
135                *out = '\n';
136                out++;
137                outlen--;
138        }
139        if (outlen < 1)
140                return SC_ERROR_BUFFER_TOO_SMALL;
141        *out = 0;
142
143        return 0;
144}
145
146int sc_base64_decode(const char *in, u8 *out, size_t outlen)
147{
148        int len = 0, r, skip;
149        unsigned int i;
150
151        while ((r = from_base64(in, &i, &skip)) > 0) {
152                int finished = 0, s = 16;
153
154                if (r < 3)
155                        finished = 1;
156                while (r--) {
157                        if (outlen <= 0)
158                                return SC_ERROR_BUFFER_TOO_SMALL;
159                        *out++ = i >> s;
160                        s -= 8;
161                        outlen--;
162                        len++;
163                }
164                in += skip;
165                if (finished || *in == 0)
166                        return len;
167        }
168        if (r == 0)
169                return len;
170        return SC_ERROR_INVALID_ARGUMENTS;
171}
Note: See TracBrowser for help on using the browser.