xref: /netbsd-src/external/bsd/openldap/dist/libraries/libldap/lbase64.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
1*549b59edSchristos /*	$NetBSD: lbase64.c,v 1.2 2021/08/14 16:14:56 christos Exp $	*/
2e670fd5cSchristos 
3e670fd5cSchristos /* lbase64.c - routines for dealing with base64 strings */
4e670fd5cSchristos /* $OpenLDAP$ */
5e670fd5cSchristos /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6e670fd5cSchristos  *
7e670fd5cSchristos  * Copyright 1998-2021 The OpenLDAP Foundation.
8e670fd5cSchristos  * All rights reserved.
9e670fd5cSchristos  *
10e670fd5cSchristos  * Redistribution and use in source and binary forms, with or without
11e670fd5cSchristos  * modification, are permitted only as authorized by the OpenLDAP
12e670fd5cSchristos  * Public License.
13e670fd5cSchristos  *
14e670fd5cSchristos  * A copy of this license is available in the file LICENSE in the
15e670fd5cSchristos  * top-level directory of the distribution or, alternatively, at
16e670fd5cSchristos  * <http://www.OpenLDAP.org/license.html>.
17e670fd5cSchristos  */
18e670fd5cSchristos /* Portions Copyright (c) 1992-1996 Regents of the University of Michigan.
19e670fd5cSchristos  * All rights reserved.
20e670fd5cSchristos  *
21e670fd5cSchristos  * Redistribution and use in source and binary forms are permitted
22e670fd5cSchristos  * provided that this notice is preserved and that due credit is given
23e670fd5cSchristos  * to the University of Michigan at Ann Arbor.  The name of the
24e670fd5cSchristos  * University may not be used to endorse or promote products derived
25e670fd5cSchristos  * from this software without specific prior written permission.  This
26e670fd5cSchristos  * software is provided ``as is'' without express or implied warranty.
27e670fd5cSchristos  */
28e670fd5cSchristos /* This work was originally developed by the University of Michigan
29e670fd5cSchristos  * and distributed as part of U-MICH LDAP.
30e670fd5cSchristos  */
31e670fd5cSchristos 
32e670fd5cSchristos #include <sys/cdefs.h>
33*549b59edSchristos __RCSID("$NetBSD: lbase64.c,v 1.2 2021/08/14 16:14:56 christos Exp $");
34e670fd5cSchristos 
35e670fd5cSchristos #include "portable.h"
36e670fd5cSchristos 
37e670fd5cSchristos #include "ldap-int.h"
38e670fd5cSchristos 
39e670fd5cSchristos #define RIGHT2			0x03
40e670fd5cSchristos #define RIGHT4			0x0f
41e670fd5cSchristos 
42e670fd5cSchristos static const unsigned char b642nib[0x80] = {
43e670fd5cSchristos 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
44e670fd5cSchristos 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
45e670fd5cSchristos 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
46e670fd5cSchristos 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
47e670fd5cSchristos 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
48e670fd5cSchristos 	0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
49e670fd5cSchristos 	0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
50e670fd5cSchristos 	0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
51e670fd5cSchristos 	0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
52e670fd5cSchristos 	0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
53e670fd5cSchristos 	0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
54e670fd5cSchristos 	0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
55e670fd5cSchristos 	0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
56e670fd5cSchristos 	0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
57e670fd5cSchristos 	0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
58e670fd5cSchristos 	0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff
59e670fd5cSchristos };
60e670fd5cSchristos 
61e670fd5cSchristos int
ldap_int_decode_b64_inplace(struct berval * value)62e670fd5cSchristos ldap_int_decode_b64_inplace( struct berval *value )
63e670fd5cSchristos {
64e670fd5cSchristos 	char	*p, *end, *byte;
65e670fd5cSchristos 	char	nib;
66e670fd5cSchristos 
67e670fd5cSchristos 	byte = value->bv_val;
68e670fd5cSchristos 	end = value->bv_val + value->bv_len;
69e670fd5cSchristos 
70e670fd5cSchristos 	for ( p = value->bv_val, value->bv_len = 0;
71e670fd5cSchristos 		p < end;
72e670fd5cSchristos 		p += 4, value->bv_len += 3 )
73e670fd5cSchristos 	{
74e670fd5cSchristos 		int i;
75e670fd5cSchristos 		for ( i = 0; i < 4; i++ ) {
76e670fd5cSchristos 			if ( p[i] != '=' && (p[i] & 0x80 ||
77e670fd5cSchristos 			    b642nib[ p[i] & 0x7f ] > 0x3f) ) {
78e670fd5cSchristos 				Debug2( LDAP_DEBUG_ANY,
79e670fd5cSchristos 					_("ldap_pvt_decode_b64_inplace: invalid base64 encoding"
80e670fd5cSchristos 					" char (%c) 0x%x\n"), p[i], p[i] );
81e670fd5cSchristos 				return( -1 );
82e670fd5cSchristos 			}
83e670fd5cSchristos 		}
84e670fd5cSchristos 
85e670fd5cSchristos 		/* first digit */
86e670fd5cSchristos 		nib = b642nib[ p[0] & 0x7f ];
87e670fd5cSchristos 		byte[0] = nib << 2;
88e670fd5cSchristos 		/* second digit */
89e670fd5cSchristos 		nib = b642nib[ p[1] & 0x7f ];
90e670fd5cSchristos 		byte[0] |= nib >> 4;
91e670fd5cSchristos 		byte[1] = (nib & RIGHT4) << 4;
92e670fd5cSchristos 		/* third digit */
93e670fd5cSchristos 		if ( p[2] == '=' ) {
94e670fd5cSchristos 			value->bv_len += 1;
95e670fd5cSchristos 			break;
96e670fd5cSchristos 		}
97e670fd5cSchristos 		nib = b642nib[ p[2] & 0x7f ];
98e670fd5cSchristos 		byte[1] |= nib >> 2;
99e670fd5cSchristos 		byte[2] = (nib & RIGHT2) << 6;
100e670fd5cSchristos 		/* fourth digit */
101e670fd5cSchristos 		if ( p[3] == '=' ) {
102e670fd5cSchristos 			value->bv_len += 2;
103e670fd5cSchristos 			break;
104e670fd5cSchristos 		}
105e670fd5cSchristos 		nib = b642nib[ p[3] & 0x7f ];
106e670fd5cSchristos 		byte[2] |= nib;
107e670fd5cSchristos 
108e670fd5cSchristos 		byte += 3;
109e670fd5cSchristos 	}
110e670fd5cSchristos 	value->bv_val[ value->bv_len ] = '\0';
111e670fd5cSchristos 
112e670fd5cSchristos     return LDAP_SUCCESS;
113e670fd5cSchristos }
114