18d2aee6bSAdrien Destugues/*	$NetBSD: base64.c,v 1.14 2012/06/25 22:32:44 abs Exp $	*/
28d2aee6bSAdrien Destugues
38d2aee6bSAdrien Destugues/*
48d2aee6bSAdrien Destugues * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
58d2aee6bSAdrien Destugues * Copyright (c) 1996-1999 by Internet Software Consortium.
68d2aee6bSAdrien Destugues *
78d2aee6bSAdrien Destugues * Permission to use, copy, modify, and distribute this software for any
88d2aee6bSAdrien Destugues * purpose with or without fee is hereby granted, provided that the above
98d2aee6bSAdrien Destugues * copyright notice and this permission notice appear in all copies.
108d2aee6bSAdrien Destugues *
118d2aee6bSAdrien Destugues * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
128d2aee6bSAdrien Destugues * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
138d2aee6bSAdrien Destugues * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
148d2aee6bSAdrien Destugues * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
158d2aee6bSAdrien Destugues * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
168d2aee6bSAdrien Destugues * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
178d2aee6bSAdrien Destugues * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
188d2aee6bSAdrien Destugues */
198d2aee6bSAdrien Destugues
208d2aee6bSAdrien Destugues/*
218d2aee6bSAdrien Destugues * Portions Copyright (c) 1995 by International Business Machines, Inc.
228d2aee6bSAdrien Destugues *
238d2aee6bSAdrien Destugues * International Business Machines, Inc. (hereinafter called IBM) grants
248d2aee6bSAdrien Destugues * permission under its copyrights to use, copy, modify, and distribute this
258d2aee6bSAdrien Destugues * Software with or without fee, provided that the above copyright notice and
268d2aee6bSAdrien Destugues * all paragraphs of this notice appear in all copies, and that the name of IBM
278d2aee6bSAdrien Destugues * not be used in connection with the marketing of any product incorporating
288d2aee6bSAdrien Destugues * the Software or modifications thereof, without specific, written prior
298d2aee6bSAdrien Destugues * permission.
308d2aee6bSAdrien Destugues *
318d2aee6bSAdrien Destugues * To the extent it has a right to do so, IBM grants an immunity from suit
328d2aee6bSAdrien Destugues * under its patents, if any, for the use, sale or manufacture of products to
338d2aee6bSAdrien Destugues * the extent that such products are used for performing Domain Name System
348d2aee6bSAdrien Destugues * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
358d2aee6bSAdrien Destugues * granted for any product per se or for any other function of any product.
368d2aee6bSAdrien Destugues *
378d2aee6bSAdrien Destugues * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
388d2aee6bSAdrien Destugues * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
398d2aee6bSAdrien Destugues * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
408d2aee6bSAdrien Destugues * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
418d2aee6bSAdrien Destugues * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
428d2aee6bSAdrien Destugues * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
438d2aee6bSAdrien Destugues */
448d2aee6bSAdrien Destugues
458d2aee6bSAdrien Destugues#include <sys/cdefs.h>
468d2aee6bSAdrien Destugues#if defined(LIBC_SCCS) && !defined(lint)
478d2aee6bSAdrien Destugues#if 0
488d2aee6bSAdrien Destuguesstatic const char rcsid[] = "Id: base64.c,v 1.4 2005/04/27 04:56:34 sra Exp";
498d2aee6bSAdrien Destugues#else
508d2aee6bSAdrien Destugues__RCSID("$NetBSD: base64.c,v 1.14 2012/06/25 22:32:44 abs Exp $");
518d2aee6bSAdrien Destugues#endif
528d2aee6bSAdrien Destugues#endif /* LIBC_SCCS and not lint */
538d2aee6bSAdrien Destugues
548d2aee6bSAdrien Destugues#include "port_before.h"
558d2aee6bSAdrien Destugues
568d2aee6bSAdrien Destugues#include <sys/types.h>
578d2aee6bSAdrien Destugues#include <sys/param.h>
588d2aee6bSAdrien Destugues#include <sys/socket.h>
598d2aee6bSAdrien Destugues
608d2aee6bSAdrien Destugues#include <netinet/in.h>
618d2aee6bSAdrien Destugues#include <arpa/inet.h>
628d2aee6bSAdrien Destugues#include <arpa/nameser.h>
638d2aee6bSAdrien Destugues
648d2aee6bSAdrien Destugues#include <assert.h>
658d2aee6bSAdrien Destugues#include <ctype.h>
668d2aee6bSAdrien Destugues#include <resolv.h>
678d2aee6bSAdrien Destugues#include <stdio.h>
688d2aee6bSAdrien Destugues#include <stdlib.h>
698d2aee6bSAdrien Destugues#include <string.h>
708d2aee6bSAdrien Destugues
718d2aee6bSAdrien Destugues#include "port_after.h"
728d2aee6bSAdrien Destugues
738d2aee6bSAdrien Destugues#define Assert(Cond) if (!(Cond)) abort()
748d2aee6bSAdrien Destugues
758d2aee6bSAdrien Destuguesstatic const char Base64[] =
768d2aee6bSAdrien Destugues	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
778d2aee6bSAdrien Destuguesstatic const char Pad64 = '=';
788d2aee6bSAdrien Destugues
798d2aee6bSAdrien Destugues/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
808d2aee6bSAdrien Destugues   The following encoding technique is taken from RFC1521 by Borenstein
818d2aee6bSAdrien Destugues   and Freed.  It is reproduced here in a slightly edited form for
828d2aee6bSAdrien Destugues   convenience.
838d2aee6bSAdrien Destugues
848d2aee6bSAdrien Destugues   A 65-character subset of US-ASCII is used, enabling 6 bits to be
858d2aee6bSAdrien Destugues   represented per printable character. (The extra 65th character, "=",
868d2aee6bSAdrien Destugues   is used to signify a special processing function.)
878d2aee6bSAdrien Destugues
888d2aee6bSAdrien Destugues   The encoding process represents 24-bit groups of input bits as output
898d2aee6bSAdrien Destugues   strings of 4 encoded characters. Proceeding from left to right, a
908d2aee6bSAdrien Destugues   24-bit input group is formed by concatenating 3 8-bit input groups.
918d2aee6bSAdrien Destugues   These 24 bits are then treated as 4 concatenated 6-bit groups, each
928d2aee6bSAdrien Destugues   of which is translated into a single digit in the base64 alphabet.
938d2aee6bSAdrien Destugues
948d2aee6bSAdrien Destugues   Each 6-bit group is used as an index into an array of 64 printable
958d2aee6bSAdrien Destugues   characters. The character referenced by the index is placed in the
968d2aee6bSAdrien Destugues   output string.
978d2aee6bSAdrien Destugues
988d2aee6bSAdrien Destugues                         Table 1: The Base64 Alphabet
998d2aee6bSAdrien Destugues
1008d2aee6bSAdrien Destugues      Value Encoding  Value Encoding  Value Encoding  Value Encoding
1018d2aee6bSAdrien Destugues          0 A            17 R            34 i            51 z
1028d2aee6bSAdrien Destugues          1 B            18 S            35 j            52 0
1038d2aee6bSAdrien Destugues          2 C            19 T            36 k            53 1
1048d2aee6bSAdrien Destugues          3 D            20 U            37 l            54 2
1058d2aee6bSAdrien Destugues          4 E            21 V            38 m            55 3
1068d2aee6bSAdrien Destugues          5 F            22 W            39 n            56 4
1078d2aee6bSAdrien Destugues          6 G            23 X            40 o            57 5
1088d2aee6bSAdrien Destugues          7 H            24 Y            41 p            58 6
1098d2aee6bSAdrien Destugues          8 I            25 Z            42 q            59 7
1108d2aee6bSAdrien Destugues          9 J            26 a            43 r            60 8
1118d2aee6bSAdrien Destugues         10 K            27 b            44 s            61 9
1128d2aee6bSAdrien Destugues         11 L            28 c            45 t            62 +
1138d2aee6bSAdrien Destugues         12 M            29 d            46 u            63 /
1148d2aee6bSAdrien Destugues         13 N            30 e            47 v
1158d2aee6bSAdrien Destugues         14 O            31 f            48 w         (pad) =
1168d2aee6bSAdrien Destugues         15 P            32 g            49 x
1178d2aee6bSAdrien Destugues         16 Q            33 h            50 y
1188d2aee6bSAdrien Destugues
1198d2aee6bSAdrien Destugues   Special processing is performed if fewer than 24 bits are available
1208d2aee6bSAdrien Destugues   at the end of the data being encoded.  A full encoding quantum is
1218d2aee6bSAdrien Destugues   always completed at the end of a quantity.  When fewer than 24 input
1228d2aee6bSAdrien Destugues   bits are available in an input group, zero bits are added (on the
1238d2aee6bSAdrien Destugues   right) to form an integral number of 6-bit groups.  Padding at the
1248d2aee6bSAdrien Destugues   end of the data is performed using the '=' character.
1258d2aee6bSAdrien Destugues
1268d2aee6bSAdrien Destugues   Since all base64 input is an integral number of octets, only the
1278d2aee6bSAdrien Destugues         -------------------------------------------------
1288d2aee6bSAdrien Destugues   following cases can arise:
1298d2aee6bSAdrien Destugues
1308d2aee6bSAdrien Destugues       (1) the final quantum of encoding input is an integral
1318d2aee6bSAdrien Destugues           multiple of 24 bits; here, the final unit of encoded
1328d2aee6bSAdrien Destugues	   output will be an integral multiple of 4 characters
1338d2aee6bSAdrien Destugues	   with no "=" padding,
1348d2aee6bSAdrien Destugues       (2) the final quantum of encoding input is exactly 8 bits;
1358d2aee6bSAdrien Destugues           here, the final unit of encoded output will be two
1368d2aee6bSAdrien Destugues	   characters followed by two "=" padding characters, or
1378d2aee6bSAdrien Destugues       (3) the final quantum of encoding input is exactly 16 bits;
1388d2aee6bSAdrien Destugues           here, the final unit of encoded output will be three
1398d2aee6bSAdrien Destugues	   characters followed by one "=" padding character.
1408d2aee6bSAdrien Destugues   */
1418d2aee6bSAdrien Destugues
1428d2aee6bSAdrien Destuguesint
1438d2aee6bSAdrien Destuguesb64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) {
1448d2aee6bSAdrien Destugues	size_t datalength = 0;
1458d2aee6bSAdrien Destugues	u_char input[3];
1468d2aee6bSAdrien Destugues	u_char output[4];
1478d2aee6bSAdrien Destugues	size_t i;
1488d2aee6bSAdrien Destugues
1498d2aee6bSAdrien Destugues	assert(src != NULL);
1508d2aee6bSAdrien Destugues	assert(target != NULL);
1518d2aee6bSAdrien Destugues
1528d2aee6bSAdrien Destugues	while (2U < srclength) {
1538d2aee6bSAdrien Destugues		input[0] = *src++;
1548d2aee6bSAdrien Destugues		input[1] = *src++;
1558d2aee6bSAdrien Destugues		input[2] = *src++;
1568d2aee6bSAdrien Destugues		srclength -= 3;
1578d2aee6bSAdrien Destugues
1588d2aee6bSAdrien Destugues		output[0] = (u_int32_t)input[0] >> 2;
1598d2aee6bSAdrien Destugues		output[1] = ((u_int32_t)(input[0] & 0x03) << 4) +
1608d2aee6bSAdrien Destugues		    ((u_int32_t)input[1] >> 4);
1618d2aee6bSAdrien Destugues		output[2] = ((u_int32_t)(input[1] & 0x0f) << 2) +
1628d2aee6bSAdrien Destugues		    ((u_int32_t)input[2] >> 6);
1638d2aee6bSAdrien Destugues		output[3] = input[2] & 0x3f;
1648d2aee6bSAdrien Destugues		Assert(output[0] < 64);
1658d2aee6bSAdrien Destugues		Assert(output[1] < 64);
1668d2aee6bSAdrien Destugues		Assert(output[2] < 64);
1678d2aee6bSAdrien Destugues		Assert(output[3] < 64);
1688d2aee6bSAdrien Destugues
1698d2aee6bSAdrien Destugues		if (datalength + 4 > targsize)
1708d2aee6bSAdrien Destugues			return (-1);
1718d2aee6bSAdrien Destugues		target[datalength++] = Base64[output[0]];
1728d2aee6bSAdrien Destugues		target[datalength++] = Base64[output[1]];
1738d2aee6bSAdrien Destugues		target[datalength++] = Base64[output[2]];
1748d2aee6bSAdrien Destugues		target[datalength++] = Base64[output[3]];
1758d2aee6bSAdrien Destugues	}
1768d2aee6bSAdrien Destugues
1778d2aee6bSAdrien Destugues	/* Now we worry about padding. */
1788d2aee6bSAdrien Destugues	if (0U != srclength) {
1798d2aee6bSAdrien Destugues		/* Get what's left. */
1808d2aee6bSAdrien Destugues		input[0] = input[1] = input[2] = '\0';
1818d2aee6bSAdrien Destugues		for (i = 0; i < srclength; i++)
1828d2aee6bSAdrien Destugues			input[i] = *src++;
1838d2aee6bSAdrien Destugues
1848d2aee6bSAdrien Destugues		output[0] = (u_int32_t)input[0] >> 2;
1858d2aee6bSAdrien Destugues		output[1] = ((u_int32_t)(input[0] & 0x03) << 4) +
1868d2aee6bSAdrien Destugues		    ((u_int32_t)input[1] >> 4);
1878d2aee6bSAdrien Destugues		output[2] = ((u_int32_t)(input[1] & 0x0f) << 2) +
1888d2aee6bSAdrien Destugues		    ((u_int32_t)input[2] >> 6);
1898d2aee6bSAdrien Destugues		Assert(output[0] < 64);
1908d2aee6bSAdrien Destugues		Assert(output[1] < 64);
1918d2aee6bSAdrien Destugues		Assert(output[2] < 64);
1928d2aee6bSAdrien Destugues
1938d2aee6bSAdrien Destugues		if (datalength + 4 > targsize)
1948d2aee6bSAdrien Destugues			return (-1);
1958d2aee6bSAdrien Destugues		target[datalength++] = Base64[output[0]];
1968d2aee6bSAdrien Destugues		target[datalength++] = Base64[output[1]];
1978d2aee6bSAdrien Destugues		if (srclength == 1U)
1988d2aee6bSAdrien Destugues			target[datalength++] = Pad64;
1998d2aee6bSAdrien Destugues		else
2008d2aee6bSAdrien Destugues			target[datalength++] = Base64[output[2]];
2018d2aee6bSAdrien Destugues		target[datalength++] = Pad64;
2028d2aee6bSAdrien Destugues	}
2038d2aee6bSAdrien Destugues	if (datalength >= targsize)
2048d2aee6bSAdrien Destugues		return (-1);
2058d2aee6bSAdrien Destugues	target[datalength] = '\0';	/*%< Returned value doesn't count \\0. */
2068d2aee6bSAdrien Destugues	assert (datalength <= (size_t)INT_MAX);
2078d2aee6bSAdrien Destugues	return (int)datalength;
2088d2aee6bSAdrien Destugues}
2098d2aee6bSAdrien Destugues
2108d2aee6bSAdrien Destugues/* skips all whitespace anywhere.
2118d2aee6bSAdrien Destugues   converts characters, four at a time, starting at (or after)
2128d2aee6bSAdrien Destugues   src from base - 64 numbers into three 8 bit bytes in the target area.
2138d2aee6bSAdrien Destugues   it returns the number of data bytes stored at the target, or -1 on error.
2148d2aee6bSAdrien Destugues */
2158d2aee6bSAdrien Destugues
2168d2aee6bSAdrien Destuguesint
2178d2aee6bSAdrien Destuguesb64_pton(char const *src, u_char *target, size_t targsize)
2188d2aee6bSAdrien Destugues{
2198d2aee6bSAdrien Destugues	size_t tarindex;
2208d2aee6bSAdrien Destugues	int state, ch;
2218d2aee6bSAdrien Destugues	char *pos;
2228d2aee6bSAdrien Destugues
2238d2aee6bSAdrien Destugues	assert(src != NULL);
2248d2aee6bSAdrien Destugues	assert(target != NULL);
2258d2aee6bSAdrien Destugues
2268d2aee6bSAdrien Destugues	state = 0;
2278d2aee6bSAdrien Destugues	tarindex = 0;
2288d2aee6bSAdrien Destugues
2298d2aee6bSAdrien Destugues	while ((ch = (u_char) *src++) != '\0') {
2308d2aee6bSAdrien Destugues		if (isspace(ch))	/*%< Skip whitespace anywhere. */
2318d2aee6bSAdrien Destugues			continue;
2328d2aee6bSAdrien Destugues
2338d2aee6bSAdrien Destugues		if (ch == Pad64)
2348d2aee6bSAdrien Destugues			break;
2358d2aee6bSAdrien Destugues
2368d2aee6bSAdrien Destugues		pos = strchr(Base64, ch);
2378d2aee6bSAdrien Destugues		if (pos == 0) 		/*%< A non-base64 character. */
2388d2aee6bSAdrien Destugues			return (-1);
2398d2aee6bSAdrien Destugues
2408d2aee6bSAdrien Destugues		switch (state) {
2418d2aee6bSAdrien Destugues		case 0:
2428d2aee6bSAdrien Destugues			if (target) {
2438d2aee6bSAdrien Destugues				if ((size_t)tarindex >= targsize)
2448d2aee6bSAdrien Destugues					return (-1);
2458d2aee6bSAdrien Destugues				target[tarindex] =
2468d2aee6bSAdrien Destugues				    (unsigned char)(pos - Base64) << 2;
2478d2aee6bSAdrien Destugues			}
2488d2aee6bSAdrien Destugues			state = 1;
2498d2aee6bSAdrien Destugues			break;
2508d2aee6bSAdrien Destugues		case 1:
2518d2aee6bSAdrien Destugues			if (target) {
2528d2aee6bSAdrien Destugues				if ((size_t)tarindex + 1 >= targsize)
2538d2aee6bSAdrien Destugues					return (-1);
2548d2aee6bSAdrien Destugues				target[tarindex] |=
2558d2aee6bSAdrien Destugues				    (u_int32_t)(pos - Base64) >> 4;
2568d2aee6bSAdrien Destugues				target[tarindex+1]  =
2578d2aee6bSAdrien Destugues				    (unsigned char)
2588d2aee6bSAdrien Destugues				    (((pos - Base64) & 0x0f) << 4);
2598d2aee6bSAdrien Destugues			}
2608d2aee6bSAdrien Destugues			tarindex++;
2618d2aee6bSAdrien Destugues			state = 2;
2628d2aee6bSAdrien Destugues			break;
2638d2aee6bSAdrien Destugues		case 2:
2648d2aee6bSAdrien Destugues			if (target) {
2658d2aee6bSAdrien Destugues				if ((size_t)tarindex + 1 >= targsize)
2668d2aee6bSAdrien Destugues					return (-1);
2678d2aee6bSAdrien Destugues				target[tarindex] |=
2688d2aee6bSAdrien Destugues					(u_int32_t)(pos - Base64) >> 2;
2698d2aee6bSAdrien Destugues				target[tarindex+1] =
2708d2aee6bSAdrien Destugues				    (unsigned char)
2718d2aee6bSAdrien Destugues				    (((pos - Base64) & 0x03) << 6);
2728d2aee6bSAdrien Destugues			}
2738d2aee6bSAdrien Destugues			tarindex++;
2748d2aee6bSAdrien Destugues			state = 3;
2758d2aee6bSAdrien Destugues			break;
2768d2aee6bSAdrien Destugues		case 3:
2778d2aee6bSAdrien Destugues			if (target) {
2788d2aee6bSAdrien Destugues				if ((size_t)tarindex >= targsize)
2798d2aee6bSAdrien Destugues					return (-1);
2808d2aee6bSAdrien Destugues				target[tarindex] |=
2818d2aee6bSAdrien Destugues				    (unsigned char)(pos - Base64);
2828d2aee6bSAdrien Destugues			}
2838d2aee6bSAdrien Destugues			tarindex++;
2848d2aee6bSAdrien Destugues			state = 0;
2858d2aee6bSAdrien Destugues			break;
2868d2aee6bSAdrien Destugues		default:
2878d2aee6bSAdrien Destugues			abort();
2888d2aee6bSAdrien Destugues		}
2898d2aee6bSAdrien Destugues	}
2908d2aee6bSAdrien Destugues
2918d2aee6bSAdrien Destugues	/*
2928d2aee6bSAdrien Destugues	 * We are done decoding Base-64 chars.  Let's see if we ended
2938d2aee6bSAdrien Destugues	 * on a byte boundary, and/or with erroneous trailing characters.
2948d2aee6bSAdrien Destugues	 */
2958d2aee6bSAdrien Destugues
2968d2aee6bSAdrien Destugues	if (ch == Pad64) {		/*%< We got a pad char. */
2978d2aee6bSAdrien Destugues		ch = *src++;		/*%< Skip it, get next. */
2988d2aee6bSAdrien Destugues		switch (state) {
2998d2aee6bSAdrien Destugues		case 0:		/*%< Invalid = in first position */
3008d2aee6bSAdrien Destugues		case 1:		/*%< Invalid = in second position */
3018d2aee6bSAdrien Destugues			return (-1);
3028d2aee6bSAdrien Destugues
3038d2aee6bSAdrien Destugues		case 2:		/*%< Valid, means one byte of info */
3048d2aee6bSAdrien Destugues			/* Skip any number of spaces. */
3058d2aee6bSAdrien Destugues			for (; ch != '\0'; ch = (u_char) *src++)
3068d2aee6bSAdrien Destugues				if (!isspace(ch))
3078d2aee6bSAdrien Destugues					break;
3088d2aee6bSAdrien Destugues			/* Make sure there is another trailing = sign. */
3098d2aee6bSAdrien Destugues			if (ch != Pad64)
3108d2aee6bSAdrien Destugues				return (-1);
3118d2aee6bSAdrien Destugues			ch = *src++;		/*%< Skip the = */
3128d2aee6bSAdrien Destugues			/* Fall through to "single trailing =" case. */
3138d2aee6bSAdrien Destugues			/* FALLTHROUGH */
3148d2aee6bSAdrien Destugues
3158d2aee6bSAdrien Destugues		case 3:		/*%< Valid, means two bytes of info */
3168d2aee6bSAdrien Destugues			/*
3178d2aee6bSAdrien Destugues			 * We know this char is an =.  Is there anything but
3188d2aee6bSAdrien Destugues			 * whitespace after it?
3198d2aee6bSAdrien Destugues			 */
3208d2aee6bSAdrien Destugues			for (; ch != '\0'; ch = (u_char) *src++)
3218d2aee6bSAdrien Destugues				if (!isspace(ch))
3228d2aee6bSAdrien Destugues					return (-1);
3238d2aee6bSAdrien Destugues
3248d2aee6bSAdrien Destugues			/*
3258d2aee6bSAdrien Destugues			 * Now make sure for cases 2 and 3 that the "extra"
3268d2aee6bSAdrien Destugues			 * bits that slopped past the last full byte were
3278d2aee6bSAdrien Destugues			 * zeros.  If we don't check them, they become a
3288d2aee6bSAdrien Destugues			 * subliminal channel.
3298d2aee6bSAdrien Destugues			 */
3308d2aee6bSAdrien Destugues			if (target && target[tarindex] != 0)
3318d2aee6bSAdrien Destugues				return (-1);
3328d2aee6bSAdrien Destugues		}
3338d2aee6bSAdrien Destugues	} else {
3348d2aee6bSAdrien Destugues		/*
3358d2aee6bSAdrien Destugues		 * We ended by seeing the end of the string.  Make sure we
3368d2aee6bSAdrien Destugues		 * have no partial bytes lying around.
3378d2aee6bSAdrien Destugues		 */
3388d2aee6bSAdrien Destugues		if (state != 0)
3398d2aee6bSAdrien Destugues			return (-1);
3408d2aee6bSAdrien Destugues	}
3418d2aee6bSAdrien Destugues
3428d2aee6bSAdrien Destugues	assert(tarindex <= (size_t)INT_MAX);
3438d2aee6bSAdrien Destugues	return (int)tarindex;
3448d2aee6bSAdrien Destugues}
3458d2aee6bSAdrien Destugues
3468d2aee6bSAdrien Destugues/*! \file */
347