a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * CDDL HEADER START
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * The contents of this file are subject to the terms of the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Common Development and Distribution License (the "License").
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * You may not use this file except in compliance with the License.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * or http://www.opensolaris.org/os/licensing.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * See the License for the specific language governing permissions
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * and limitations under the License.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * When distributing Covered Code, include this CDDL HEADER in each
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * If applicable, add the following below this CDDL HEADER, with the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * fields enclosed by brackets "[]" replaced with your own identifying
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * information: Portions Copyright [yyyy] [name of copyright owner]
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * CDDL HEADER END
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Use is subject to license terms.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/types.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#ifdef _KERNEL
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/sunddi.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/errno.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#else
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <string.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <errno.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif /* _KERNEL */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * base64 decoding table (from uudecode.c)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/* BEGIN CSTYLED */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap static char base64_decode_tab[] = {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377',
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377',
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377',
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377',
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377',
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap '\377', '\377', '\377', 62, '\377', '\377', '\377', 63,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 52, 53, 54, 55, 56, 57, 58, 59,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 60, 61, '\377', '\377', '\377', '\377', '\377', '\377',
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap '\377', 0, 1, 2, 3, 4, 5, 6,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 7, 8, 9, 10, 11, 12, 13, 14,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 15, 16, 17, 18, 19, 20, 21, 22,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 23, 24, 25, '\377', '\377', '\377', '\377', '\377',
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap '\377', 26, 27, 28, 29, 30, 31, 32,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 33, 34, 35, 36, 37, 38, 39, 40,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 41, 42, 43, 44, 45, 46, 47, 48,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 49, 50, 51, '\377', '\377', '\377', '\377', '\377'
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap};
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/* END CSTYLED */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/* true if the character is in the base64 encoding table */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#define validbase64(c) (('A' <= (c) && (c) <= 'Z') || \
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ('a' <= (c) && (c) <= 'z') || \
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ('0' <= (c) && (c) <= '9') || \
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (c) == '+' || (c) == '/')
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapoutdec64(unsigned char *out, unsigned char *chr, int num)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap unsigned char char1, char2, char3, char4;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap unsigned char *outptr = out;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int rc = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap switch (num) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case 0:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case 1: /* these are impossible */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap default:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case 2: /* 2 base64 bytes == 1 decoded byte */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap char1 = base64_decode_tab[chr[0]] & 0xFF;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap char2 = base64_decode_tab[chr[1]] & 0xFF;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *(outptr++) = ((char1 << 2) & 0xFC) |
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ((char2 >> 4) & 0x03);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rc = 1;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case 3: /* 3 base64 bytes == 2 decoded bytes */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap char1 = base64_decode_tab[chr[0]] & 0xFF;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap char2 = base64_decode_tab[chr[1]] & 0xFF;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap char3 = base64_decode_tab[chr[2]] & 0xFF;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *(outptr++) = ((char1 << 2) & 0xFC) |
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ((char2 >> 4) & 0x03);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *(outptr++) = ((char2 << 4) & 0xF0) |
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ((char3 >> 2) & 0x0F);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rc = 2;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case 4: /* 4 base64 bytes == 3 decoded bytes */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap char1 = base64_decode_tab[chr[0]] & 0xFF;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap char2 = base64_decode_tab[chr[1]] & 0xFF;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap char3 = base64_decode_tab[chr[2]] & 0xFF;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap char4 = base64_decode_tab[chr[3]] & 0xFF;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *(outptr++) = ((char1 << 2) & 0xFC) |
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ((char2 >> 4) & 0x03);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *(outptr++) = ((char2 << 4) & 0xF0) |
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ((char3 >> 2) & 0x0F);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *(outptr++) = ((char3 << 6) & 0xC0) |
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (char4 & 0x3F);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rc = 3;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (rc);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#define BUFSIZE 12
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapint
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapiscsi_base64_str_to_binary(char *hstr, int hstr_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint8_t *binary, int binary_buf_len, int *out_len)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap char *iptr;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint8_t tmp_out[BUFSIZE];
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int octets, endseen, numbase64chars;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap unsigned char chr[4], curchr;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * base64 decode algorith, adapted from uudecode.c
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * A valid base64 string is a multiple of 4 bytes in length
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((hstr_len % 4) != 0)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (EINVAL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap endseen = numbase64chars = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *out_len = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iptr = hstr;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap while (((curchr = *(iptr++)) != NULL) &&
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (((uintptr_t)iptr - (uintptr_t)hstr) <= hstr_len)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* decode chars */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (curchr == '=') /* if end */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap endseen++;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (validbase64(curchr))
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap chr[numbase64chars++] = curchr;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * if we've gathered 4 base64 octets
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * we need to decode and output them
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (numbase64chars == 4) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap octets = outdec64(tmp_out, chr, 4);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap numbase64chars = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (*out_len + octets > binary_buf_len)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (E2BIG);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) memcpy(binary + *out_len, tmp_out, octets);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *out_len += octets;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * handle any remaining base64 octets at end
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (endseen && numbase64chars > 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap octets = outdec64(tmp_out, chr, numbase64chars);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap numbase64chars = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (*out_len + octets > binary_buf_len)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (E2BIG);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) memcpy(binary + *out_len, tmp_out, octets);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *out_len += octets;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic char base64_encode_tab[] =
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "abcdefghijklmnopqrstuvwxyz0123456789+/";
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#define ENC(c) base64_encode_tab[(c) & 0x3f]
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#define BASE64_BUF_HAS_ROOM(bytes_needed) \
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ((optr + (bytes_needed)) <= base64_str_buf + base64_buf_len)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapint
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapiscsi_binary_to_base64_str(uint8_t *in_buf, int in_buf_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap char *base64_str_buf, int base64_buf_len)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint8_t *iptr;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap char *optr;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int in_bytes_remaining;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* base64 encode algorith, adapted from uuencode.c */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iptr = in_buf;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap optr = base64_str_buf;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * read must be a multiple of 3 bytes for
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * this algorithm to work, and also must
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * be small enough that read_size * (4/3)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * will always be 76 bytes or less, since
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * base64 lines can be no longer than that
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap while (iptr + 3 <= in_buf + in_buf_len) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (!BASE64_BUF_HAS_ROOM(4))
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (E2BIG);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *(optr++) = ENC(*iptr >> 2);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *(optr++) = ENC((*iptr << 4) & 060 |
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (*(iptr + 1) >> 4) & 017);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *(optr++) = ENC((*(iptr + 1) << 2)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap & 074 | (*(iptr + 2) >> 6) & 03);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *(optr++) = ENC(*(iptr + 2) & 077);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iptr += 3;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* need output padding ? */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap in_bytes_remaining = ((uintptr_t)in_buf + in_buf_len) - (uintptr_t)iptr;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* ASSERT(in_bytes_remaining < 3); */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap switch (in_bytes_remaining) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case 0:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* no-op - 24 bits of data encoded */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (!BASE64_BUF_HAS_ROOM(1))
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (E2BIG);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *(optr++) = '\0';
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case 1:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* 8 bits encoded - pad with 2 '=' */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (!BASE64_BUF_HAS_ROOM(5))
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (E2BIG);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *(optr++) = ENC((*iptr & 0xFC) >> 2);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *(optr++) = ENC((*iptr & 0x03) << 4);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *(optr++) = '=';
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *(optr++) = '=';
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *(optr++) = '\0';
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case 2:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* 16 bits encoded - pad with 1 '=' */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (!BASE64_BUF_HAS_ROOM(5))
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (E2BIG);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *(optr++) = ENC((*iptr & 0xFC) >> 2);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *(optr++) = ENC(((*iptr & 0x03) << 4) |
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ((*(iptr + 1) & 0xF0) >> 4));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *(optr++) = ENC((*(iptr + 1) & 0x0F) << 2);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *(optr++) = '=';
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *(optr++) = '\0';
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap default:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* impossible */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}