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