4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <sys/types.h>
28 #include <sys/sunddi.h>
29 #include <sys/errno.h>
36 * base64 decoding table (from uudecode.c)
39 static char base64_decode_tab
[] = {
40 '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377',
41 '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377',
42 '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377',
43 '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377',
44 '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377',
45 '\377', '\377', '\377', 62, '\377', '\377', '\377', 63,
46 52, 53, 54, 55, 56, 57, 58, 59,
47 60, 61, '\377', '\377', '\377', '\377', '\377', '\377',
48 '\377', 0, 1, 2, 3, 4, 5, 6,
49 7, 8, 9, 10, 11, 12, 13, 14,
50 15, 16, 17, 18, 19, 20, 21, 22,
51 23, 24, 25, '\377', '\377', '\377', '\377', '\377',
52 '\377', 26, 27, 28, 29, 30, 31, 32,
53 33, 34, 35, 36, 37, 38, 39, 40,
54 41, 42, 43, 44, 45, 46, 47, 48,
55 49, 50, 51, '\377', '\377', '\377', '\377', '\377'
59 /* true if the character is in the base64 encoding table */
60 #define validbase64(c) (('A' <= (c) && (c) <= 'Z') || \
61 ('a' <= (c) && (c) <= 'z') || \
62 ('0' <= (c) && (c) <= '9') || \
63 (c) == '+' || (c) == '/')
66 outdec64(unsigned char *out
, unsigned char *chr
, int num
)
69 unsigned char char1
, char2
, char3
, char4
;
70 unsigned char *outptr
= out
;
75 case 1: /* these are impossible */
78 case 2: /* 2 base64 bytes == 1 decoded byte */
79 char1
= base64_decode_tab
[chr
[0]] & 0xFF;
80 char2
= base64_decode_tab
[chr
[1]] & 0xFF;
81 *(outptr
++) = ((char1
<< 2) & 0xFC) |
82 ((char2
>> 4) & 0x03);
85 case 3: /* 3 base64 bytes == 2 decoded bytes */
86 char1
= base64_decode_tab
[chr
[0]] & 0xFF;
87 char2
= base64_decode_tab
[chr
[1]] & 0xFF;
88 char3
= base64_decode_tab
[chr
[2]] & 0xFF;
89 *(outptr
++) = ((char1
<< 2) & 0xFC) |
90 ((char2
>> 4) & 0x03);
91 *(outptr
++) = ((char2
<< 4) & 0xF0) |
92 ((char3
>> 2) & 0x0F);
95 case 4: /* 4 base64 bytes == 3 decoded bytes */
96 char1
= base64_decode_tab
[chr
[0]] & 0xFF;
97 char2
= base64_decode_tab
[chr
[1]] & 0xFF;
98 char3
= base64_decode_tab
[chr
[2]] & 0xFF;
99 char4
= base64_decode_tab
[chr
[3]] & 0xFF;
100 *(outptr
++) = ((char1
<< 2) & 0xFC) |
101 ((char2
>> 4) & 0x03);
102 *(outptr
++) = ((char2
<< 4) & 0xF0) |
103 ((char3
>> 2) & 0x0F);
104 *(outptr
++) = ((char3
<< 6) & 0xC0) |
115 iscsi_base64_str_to_binary(char *hstr
, int hstr_len
,
116 uint8_t *binary
, int binary_buf_len
, int *out_len
)
119 uint8_t tmp_out
[BUFSIZE
];
120 int octets
, endseen
, numbase64chars
;
121 unsigned char chr
[4], curchr
;
124 * base64 decode algorith, adapted from uudecode.c
126 * A valid base64 string is a multiple of 4 bytes in length
128 if ((hstr_len
% 4) != 0)
131 endseen
= numbase64chars
= 0;
135 while (((curchr
= *(iptr
++)) != '\0') &&
136 (((uintptr_t)iptr
- (uintptr_t)hstr
) <= hstr_len
)) {
138 if (curchr
== '=') /* if end */
141 if (validbase64(curchr
))
142 chr
[numbase64chars
++] = curchr
;
144 * if we've gathered 4 base64 octets
145 * we need to decode and output them
147 if (numbase64chars
== 4) {
148 octets
= outdec64(tmp_out
, chr
, 4);
151 if (*out_len
+ octets
> binary_buf_len
)
154 (void) memcpy(binary
+ *out_len
, tmp_out
, octets
);
159 * handle any remaining base64 octets at end
161 if (endseen
&& numbase64chars
> 0) {
162 octets
= outdec64(tmp_out
, chr
, numbase64chars
);
164 if (*out_len
+ octets
> binary_buf_len
)
167 (void) memcpy(binary
+ *out_len
, tmp_out
, octets
);
176 static char base64_encode_tab
[] =
177 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
178 "abcdefghijklmnopqrstuvwxyz0123456789+/";
180 #define ENC(c) base64_encode_tab[(c) & 0x3f]
182 #define BASE64_BUF_HAS_ROOM(bytes_needed) \
183 ((optr + (bytes_needed)) <= base64_str_buf + base64_buf_len)
186 iscsi_binary_to_base64_str(uint8_t *in_buf
, int in_buf_len
,
187 char *base64_str_buf
, int base64_buf_len
)
191 int in_bytes_remaining
;
193 /* base64 encode algorith, adapted from uuencode.c */
195 optr
= base64_str_buf
;
198 * read must be a multiple of 3 bytes for
199 * this algorithm to work, and also must
200 * be small enough that read_size * (4/3)
201 * will always be 76 bytes or less, since
202 * base64 lines can be no longer than that
204 while (iptr
+ 3 <= in_buf
+ in_buf_len
) {
205 if (!BASE64_BUF_HAS_ROOM(4))
208 *(optr
++) = ENC(*iptr
>> 2);
209 *(optr
++) = ENC((*iptr
<< 4) & 060 |
210 (*(iptr
+ 1) >> 4) & 017);
211 *(optr
++) = ENC((*(iptr
+ 1) << 2)
212 & 074 | (*(iptr
+ 2) >> 6) & 03);
213 *(optr
++) = ENC(*(iptr
+ 2) & 077);
218 /* need output padding ? */
219 in_bytes_remaining
= ((uintptr_t)in_buf
+ in_buf_len
) - (uintptr_t)iptr
;
220 /* ASSERT(in_bytes_remaining < 3); */
221 switch (in_bytes_remaining
) {
223 /* no-op - 24 bits of data encoded */
224 if (!BASE64_BUF_HAS_ROOM(1))
229 /* 8 bits encoded - pad with 2 '=' */
230 if (!BASE64_BUF_HAS_ROOM(5))
232 *(optr
++) = ENC((*iptr
& 0xFC) >> 2);
233 *(optr
++) = ENC((*iptr
& 0x03) << 4);
239 /* 16 bits encoded - pad with 1 '=' */
240 if (!BASE64_BUF_HAS_ROOM(5))
242 *(optr
++) = ENC((*iptr
& 0xFC) >> 2);
243 *(optr
++) = ENC(((*iptr
& 0x03) << 4) |
244 ((*(iptr
+ 1) & 0xF0) >> 4));
245 *(optr
++) = ENC((*(iptr
+ 1) & 0x0F) << 2);