xref: /onnv-gate/usr/src/lib/libkmf/ber_der/common/io.c (revision 3089:8ddeb2ace8aa)
1*3089Swyllys /*
2*3089Swyllys  * CDDL HEADER START
3*3089Swyllys  *
4*3089Swyllys  * The contents of this file are subject to the terms of the
5*3089Swyllys  * Common Development and Distribution License (the "License").
6*3089Swyllys  * You may not use this file except in compliance with the License.
7*3089Swyllys  *
8*3089Swyllys  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*3089Swyllys  * or http://www.opensolaris.org/os/licensing.
10*3089Swyllys  * See the License for the specific language governing permissions
11*3089Swyllys  * and limitations under the License.
12*3089Swyllys  *
13*3089Swyllys  * When distributing Covered Code, include this CDDL HEADER in each
14*3089Swyllys  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*3089Swyllys  * If applicable, add the following below this CDDL HEADER, with the
16*3089Swyllys  * fields enclosed by brackets "[]" replaced with your own identifying
17*3089Swyllys  * information: Portions Copyright [yyyy] [name of copyright owner]
18*3089Swyllys  *
19*3089Swyllys  * CDDL HEADER END
20*3089Swyllys  */
21*3089Swyllys 
22*3089Swyllys /*
23*3089Swyllys  * -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
24*3089Swyllys  *
25*3089Swyllys  * The contents of this file are subject to the Netscape Public License
26*3089Swyllys  * Version 1.0 (the "NPL"); you may not use this file except in
27*3089Swyllys  * compliance with the NPL.  You may obtain a copy of the NPL at
28*3089Swyllys  * http://www.mozilla.org/NPL/
29*3089Swyllys  *
30*3089Swyllys  * Software distributed under the NPL is distributed on an "AS IS" basis,
31*3089Swyllys  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
32*3089Swyllys  * for the specific language governing rights and limitations under the
33*3089Swyllys  * NPL.
34*3089Swyllys  *
35*3089Swyllys  * The Initial Developer of this code under the NPL is Netscape
36*3089Swyllys  * Communications Corporation.  Portions created by Netscape are
37*3089Swyllys  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
38*3089Swyllys  * Reserved.
39*3089Swyllys  */
40*3089Swyllys 
41*3089Swyllys /*
42*3089Swyllys  * Copyright (c) 1990 Regents of the University of Michigan.
43*3089Swyllys  * All rights reserved.
44*3089Swyllys  *
45*3089Swyllys  * Redistribution and use in source and binary forms are permitted
46*3089Swyllys  * provided that this notice is preserved and that due credit is given
47*3089Swyllys  * to the University of Michigan at Ann Arbor. The name of the University
48*3089Swyllys  * may not be used to endorse or promote products derived from this
49*3089Swyllys  * software without specific prior written permission. This software
50*3089Swyllys  * is provided ``as is'' without express or implied warranty.
51*3089Swyllys  */
52*3089Swyllys /*
53*3089Swyllys  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
54*3089Swyllys  * Use is subject to license terms.
55*3089Swyllys  */
56*3089Swyllys 
57*3089Swyllys #pragma ident	"%Z%%M%	%I%	%E% SMI"
58*3089Swyllys 
59*3089Swyllys 
60*3089Swyllys #include <stdlib.h>
61*3089Swyllys #include <ber_der.h>
62*3089Swyllys #include "kmfber_int.h"
63*3089Swyllys 
64*3089Swyllys #define	EXBUFSIZ	1024
65*3089Swyllys 
66*3089Swyllys /*
67*3089Swyllys  * Note: kmfber_read() only uses the ber_end and ber_ptr elements of ber.
68*3089Swyllys  * Functions like kmfber_get_tag(), kmfber_skip_tag, and kmfber_peek_tag()
69*3089Swyllys  * rely on that fact, so if this code is changed to use any additional
70*3089Swyllys  * elements of the ber structure, those functions will need to be changed
71*3089Swyllys  * as well.
72*3089Swyllys  */
73*3089Swyllys ber_int_t
74*3089Swyllys kmfber_read(BerElement *ber, char *buf, ber_len_t len)
75*3089Swyllys {
76*3089Swyllys 	size_t	actuallen;
77*3089Swyllys 	size_t	nleft;
78*3089Swyllys 
79*3089Swyllys 	nleft = ber->ber_end - ber->ber_ptr;
80*3089Swyllys 	actuallen = nleft < len ? nleft : len;
81*3089Swyllys 
82*3089Swyllys 	(void) memmove(buf, ber->ber_ptr, (size_t)actuallen);
83*3089Swyllys 
84*3089Swyllys 	ber->ber_ptr += actuallen;
85*3089Swyllys 
86*3089Swyllys 	return ((ber_int_t)actuallen);
87*3089Swyllys }
88*3089Swyllys 
89*3089Swyllys /*
90*3089Swyllys  * enlarge the ber buffer.
91*3089Swyllys  * return 0 on success, -1 on error.
92*3089Swyllys  */
93*3089Swyllys static int
94*3089Swyllys kmfber_realloc(BerElement *ber, ber_len_t len)
95*3089Swyllys {
96*3089Swyllys 	ber_uint_t	need, have, total;
97*3089Swyllys 	size_t		have_bytes;
98*3089Swyllys 	Seqorset	*s;
99*3089Swyllys 	size_t		off;
100*3089Swyllys 	char		*oldbuf;
101*3089Swyllys 
102*3089Swyllys 	have_bytes = ber->ber_end - ber->ber_buf;
103*3089Swyllys 	have = have_bytes / EXBUFSIZ;
104*3089Swyllys 	need = (len < EXBUFSIZ ? 1 : (len + (EXBUFSIZ - 1)) / EXBUFSIZ);
105*3089Swyllys 	total = have * EXBUFSIZ + need * EXBUFSIZ;
106*3089Swyllys 
107*3089Swyllys 	oldbuf = ber->ber_buf;
108*3089Swyllys 
109*3089Swyllys 	if (ber->ber_buf == NULL) {
110*3089Swyllys 		if ((ber->ber_buf = (char *)malloc((size_t)total))
111*3089Swyllys 		    == NULL) {
112*3089Swyllys 			return (-1);
113*3089Swyllys 		}
114*3089Swyllys 		ber->ber_flags &= ~KMFBER_FLAG_NO_FREE_BUFFER;
115*3089Swyllys 	} else {
116*3089Swyllys 		if (ber->ber_flags & KMFBER_FLAG_NO_FREE_BUFFER) {
117*3089Swyllys 			/* transition to malloc'd buffer */
118*3089Swyllys 			if ((ber->ber_buf = (char *)malloc(
119*3089Swyllys 			    (size_t)total)) == NULL) {
120*3089Swyllys 				return (-1);
121*3089Swyllys 			}
122*3089Swyllys 			ber->ber_flags &= ~KMFBER_FLAG_NO_FREE_BUFFER;
123*3089Swyllys 			/* copy existing data into new malloc'd buffer */
124*3089Swyllys 			(void) memmove(ber->ber_buf, oldbuf, have_bytes);
125*3089Swyllys 		} else {
126*3089Swyllys 			if ((ber->ber_buf = (char *)realloc(
127*3089Swyllys 			    ber->ber_buf, (size_t)total)) == NULL) {
128*3089Swyllys 				return (-1);
129*3089Swyllys 			}
130*3089Swyllys 		}
131*3089Swyllys 	}
132*3089Swyllys 
133*3089Swyllys 	ber->ber_end = ber->ber_buf + total;
134*3089Swyllys 
135*3089Swyllys 	/*
136*3089Swyllys 	 * If the stinking thing was moved, we need to go through and
137*3089Swyllys 	 * reset all the sos and ber pointers.  Offsets would've been
138*3089Swyllys 	 * a better idea... oh well.
139*3089Swyllys 	 */
140*3089Swyllys 
141*3089Swyllys 	if (ber->ber_buf != oldbuf) {
142*3089Swyllys 		ber->ber_ptr = ber->ber_buf + (ber->ber_ptr - oldbuf);
143*3089Swyllys 
144*3089Swyllys 		for (s = ber->ber_sos; s != NULLSEQORSET; s = s->sos_next) {
145*3089Swyllys 			off = s->sos_first - oldbuf;
146*3089Swyllys 			s->sos_first = ber->ber_buf + off;
147*3089Swyllys 
148*3089Swyllys 			off = s->sos_ptr - oldbuf;
149*3089Swyllys 			s->sos_ptr = ber->ber_buf + off;
150*3089Swyllys 		}
151*3089Swyllys 	}
152*3089Swyllys 
153*3089Swyllys 	return (0);
154*3089Swyllys }
155*3089Swyllys 
156*3089Swyllys /*
157*3089Swyllys  * returns "len" on success and -1 on failure.
158*3089Swyllys  */
159*3089Swyllys ber_int_t
160*3089Swyllys kmfber_write(BerElement *ber, char *buf, ber_len_t len, int nosos)
161*3089Swyllys {
162*3089Swyllys 	if (nosos || ber->ber_sos == NULL) {
163*3089Swyllys 		if (ber->ber_ptr + len > ber->ber_end) {
164*3089Swyllys 			if (kmfber_realloc(ber, len) != 0)
165*3089Swyllys 				return (-1);
166*3089Swyllys 		}
167*3089Swyllys 		(void) memmove(ber->ber_ptr, buf, (size_t)len);
168*3089Swyllys 		ber->ber_ptr += len;
169*3089Swyllys 		return (len);
170*3089Swyllys 	} else {
171*3089Swyllys 		if (ber->ber_sos->sos_ptr + len > ber->ber_end) {
172*3089Swyllys 			if (kmfber_realloc(ber, len) != 0)
173*3089Swyllys 				return (-1);
174*3089Swyllys 		}
175*3089Swyllys 		(void) memmove(ber->ber_sos->sos_ptr, buf, (size_t)len);
176*3089Swyllys 		ber->ber_sos->sos_ptr += len;
177*3089Swyllys 		ber->ber_sos->sos_clen += len;
178*3089Swyllys 		return (len);
179*3089Swyllys 	}
180*3089Swyllys }
181*3089Swyllys 
182*3089Swyllys void
183*3089Swyllys kmfber_free(BerElement *ber, int freebuf)
184*3089Swyllys {
185*3089Swyllys 	if (ber != NULL) {
186*3089Swyllys 		    if (freebuf &&
187*3089Swyllys 			!(ber->ber_flags & KMFBER_FLAG_NO_FREE_BUFFER)) {
188*3089Swyllys 			    free(ber->ber_buf);
189*3089Swyllys 		    }
190*3089Swyllys 		    free((char *)ber);
191*3089Swyllys 	}
192*3089Swyllys }
193*3089Swyllys 
194*3089Swyllys /* we pre-allocate a buffer to save the extra malloc later */
195*3089Swyllys BerElement *
196*3089Swyllys kmfber_alloc_t(int options)
197*3089Swyllys {
198*3089Swyllys 	BerElement	*ber;
199*3089Swyllys 
200*3089Swyllys 	if ((ber = (BerElement*)calloc(1,
201*3089Swyllys 	    sizeof (struct berelement) + EXBUFSIZ)) == NULL) {
202*3089Swyllys 		return (NULL);
203*3089Swyllys 	}
204*3089Swyllys 
205*3089Swyllys 	ber->ber_tag = KMFBER_DEFAULT;
206*3089Swyllys 	ber->ber_options = options;
207*3089Swyllys 	ber->ber_buf = (char *)ber + sizeof (struct berelement);
208*3089Swyllys 	ber->ber_ptr = ber->ber_buf;
209*3089Swyllys 	ber->ber_end = ber->ber_buf + EXBUFSIZ;
210*3089Swyllys 	ber->ber_flags = KMFBER_FLAG_NO_FREE_BUFFER;
211*3089Swyllys 
212*3089Swyllys 	return (ber);
213*3089Swyllys }
214*3089Swyllys 
215*3089Swyllys 
216*3089Swyllys BerElement *
217*3089Swyllys kmfber_alloc()
218*3089Swyllys {
219*3089Swyllys 	return (kmfber_alloc_t(0));
220*3089Swyllys }
221*3089Swyllys 
222*3089Swyllys BerElement *
223*3089Swyllys kmfder_alloc()
224*3089Swyllys {
225*3089Swyllys 	return (kmfber_alloc_t(KMFBER_OPT_USE_DER));
226*3089Swyllys }
227*3089Swyllys 
228*3089Swyllys BerElement *
229*3089Swyllys kmfber_dup(BerElement *ber)
230*3089Swyllys {
231*3089Swyllys 	BerElement	*new;
232*3089Swyllys 
233*3089Swyllys 	if ((new = kmfber_alloc()) == NULL)
234*3089Swyllys 		return (NULL);
235*3089Swyllys 
236*3089Swyllys 	*new = *ber;
237*3089Swyllys 
238*3089Swyllys 	return (new);
239*3089Swyllys }
240*3089Swyllys 
241*3089Swyllys 
242*3089Swyllys void
243*3089Swyllys ber_init_w_nullchar(BerElement *ber, int options)
244*3089Swyllys {
245*3089Swyllys 	(void) memset((char *)ber, '\0', sizeof (struct berelement));
246*3089Swyllys 	ber->ber_tag = KMFBER_DEFAULT;
247*3089Swyllys 
248*3089Swyllys 	ber->ber_options = options;
249*3089Swyllys }
250*3089Swyllys 
251*3089Swyllys 
252*3089Swyllys void
253*3089Swyllys kmfber_reset(BerElement *ber, int was_writing)
254*3089Swyllys {
255*3089Swyllys 	if (was_writing) {
256*3089Swyllys 		ber->ber_end = ber->ber_ptr;
257*3089Swyllys 		ber->ber_ptr = ber->ber_buf;
258*3089Swyllys 	} else {
259*3089Swyllys 		ber->ber_ptr = ber->ber_end;
260*3089Swyllys 	}
261*3089Swyllys 
262*3089Swyllys 	ber->ber_rwptr = NULL;
263*3089Swyllys }
264*3089Swyllys 
265*3089Swyllys 
266*3089Swyllys #ifdef KMFBER_DEBUG
267*3089Swyllys 
268*3089Swyllys void
269*3089Swyllys ber_dump(BerElement *ber, int inout)
270*3089Swyllys {
271*3089Swyllys 	char msg[128];
272*3089Swyllys 	sprintf(msg, "ber_dump: buf 0x%lx, ptr 0x%lx, rwptr 0x%lx, end 0x%lx\n",
273*3089Swyllys 	    ber->ber_buf, ber->ber_ptr, ber->ber_rwptr, ber->ber_end);
274*3089Swyllys 	ber_err_print(msg);
275*3089Swyllys 	if (inout == 1) {
276*3089Swyllys 		sprintf(msg, "          current len %ld, contents:\n",
277*3089Swyllys 		    ber->ber_end - ber->ber_ptr);
278*3089Swyllys 		ber_err_print(msg);
279*3089Swyllys 		lber_bprint(ber->ber_ptr, ber->ber_end - ber->ber_ptr);
280*3089Swyllys 	} else {
281*3089Swyllys 		sprintf(msg, "          current len %ld, contents:\n",
282*3089Swyllys 		    ber->ber_ptr - ber->ber_buf);
283*3089Swyllys 		ber_err_print(msg);
284*3089Swyllys 		lber_bprint(ber->ber_buf, ber->ber_ptr - ber->ber_buf);
285*3089Swyllys 	}
286*3089Swyllys }
287*3089Swyllys 
288*3089Swyllys void
289*3089Swyllys ber_sos_dump(Seqorset *sos)
290*3089Swyllys {
291*3089Swyllys 	char msg[80];
292*3089Swyllys 	ber_err_print("*** sos dump ***\n");
293*3089Swyllys 	while (sos != NULLSEQORSET) {
294*3089Swyllys 		sprintf(msg, "ber_sos_dump: clen %ld first 0x%lx ptr 0x%lx\n",
295*3089Swyllys 		    sos->sos_clen, sos->sos_first, sos->sos_ptr);
296*3089Swyllys 		ber_err_print(msg);
297*3089Swyllys 		sprintf(msg, "              current len %ld contents:\n",
298*3089Swyllys 		    sos->sos_ptr - sos->sos_first);
299*3089Swyllys 		ber_err_print(msg);
300*3089Swyllys 		lber_bprint(sos->sos_first, sos->sos_ptr - sos->sos_first);
301*3089Swyllys 
302*3089Swyllys 		sos = sos->sos_next;
303*3089Swyllys 	}
304*3089Swyllys 	ber_err_print("*** end dump ***\n");
305*3089Swyllys }
306*3089Swyllys 
307*3089Swyllys #endif
308*3089Swyllys 
309*3089Swyllys /* new dboreham code below: */
310*3089Swyllys struct byte_buffer  {
311*3089Swyllys 	unsigned char *p;
312*3089Swyllys 	int offset;
313*3089Swyllys 	int length;
314*3089Swyllys };
315*3089Swyllys typedef struct byte_buffer byte_buffer;
316*3089Swyllys 
317*3089Swyllys /*
318*3089Swyllys  * The kmfber_flatten routine allocates a struct berval whose contents
319*3089Swyllys  * are a BER encoding taken from the ber argument. The bvPtr pointer
320*3089Swyllys  * points to the returned berval, which must be freed using
321*3089Swyllys  * kmfber_bvfree().  This routine returns 0 on success and -1 on error.
322*3089Swyllys  * The use of kmfber_flatten on a BerElement in which all '{' and '}'
323*3089Swyllys  * format modifiers have not been properly matched can result in a
324*3089Swyllys  * berval whose contents are not a valid BER encoding.
325*3089Swyllys  * Note that the ber_ptr is not modified.
326*3089Swyllys  */
327*3089Swyllys int
328*3089Swyllys kmfber_flatten(BerElement *ber, struct berval **bvPtr)
329*3089Swyllys {
330*3089Swyllys 	struct berval *new;
331*3089Swyllys 	ber_len_t len;
332*3089Swyllys 
333*3089Swyllys 	/* allocate a struct berval */
334*3089Swyllys 	new = (struct berval *)malloc((size_t)(sizeof (struct berval)));
335*3089Swyllys 	if (new == NULL) {
336*3089Swyllys 		return (-1);
337*3089Swyllys 	}
338*3089Swyllys 	(void) memset(new, 0, sizeof (struct berval));
339*3089Swyllys 
340*3089Swyllys 	/*
341*3089Swyllys 	 * Copy everything from the BerElement's ber_buf to ber_ptr
342*3089Swyllys 	 * into the berval structure.
343*3089Swyllys 	 */
344*3089Swyllys 	if (ber == NULL) {
345*3089Swyllys 		new->bv_val = NULL;
346*3089Swyllys 		new->bv_len = 0;
347*3089Swyllys 	} else {
348*3089Swyllys 		len = ber->ber_ptr - ber->ber_buf;
349*3089Swyllys 		new->bv_val = (char *)malloc((size_t)(len + 1));
350*3089Swyllys 		if (new->bv_val == NULL) {
351*3089Swyllys 			kmfber_bvfree(new);
352*3089Swyllys 			return (-1);
353*3089Swyllys 		}
354*3089Swyllys 		(void) memmove(new->bv_val, ber->ber_buf, (size_t)len);
355*3089Swyllys 		new->bv_val[len] = '\0';
356*3089Swyllys 		new->bv_len = len;
357*3089Swyllys 	}
358*3089Swyllys 
359*3089Swyllys 	/* set bvPtr pointer to point to the returned berval */
360*3089Swyllys 	*bvPtr = new;
361*3089Swyllys 
362*3089Swyllys 	return (0);
363*3089Swyllys }
364*3089Swyllys 
365*3089Swyllys BerElement *
366*3089Swyllys kmfder_init(const struct berval *bv)
367*3089Swyllys {
368*3089Swyllys 	BerElement *ber;
369*3089Swyllys 
370*3089Swyllys 	/* construct BerElement */
371*3089Swyllys 	if ((ber = kmfber_alloc_t(KMFBER_OPT_USE_DER)) != NULL) {
372*3089Swyllys 		/* copy data from the bv argument into BerElement */
373*3089Swyllys 		/* XXXmcs: had to cast unsigned long bv_len to long */
374*3089Swyllys 		if ((kmfber_write(ber, bv->bv_val, bv->bv_len, 0)) !=
375*3089Swyllys 			(ber_slen_t)bv->bv_len) {
376*3089Swyllys 			kmfber_free(ber, 1);
377*3089Swyllys 			return (NULL);
378*3089Swyllys 		}
379*3089Swyllys 	}
380*3089Swyllys 	/*
381*3089Swyllys 	 * reset ber_ptr back to the beginning of buffer so that this new
382*3089Swyllys 	 * and initialized ber element can be READ
383*3089Swyllys 	 */
384*3089Swyllys 	kmfber_reset(ber, 1);
385*3089Swyllys 
386*3089Swyllys 	/*
387*3089Swyllys 	 * return a ptr to a new BerElement containing a copy of the data
388*3089Swyllys 	 * in the bv argument or a null pointer on error
389*3089Swyllys 	 */
390*3089Swyllys 	return (ber);
391*3089Swyllys }
392*3089Swyllys 
393*3089Swyllys BerElement *
394*3089Swyllys kmfber_init(const struct berval *bv)
395*3089Swyllys {
396*3089Swyllys 	BerElement *ber;
397*3089Swyllys 
398*3089Swyllys 	/* construct BerElement */
399*3089Swyllys 	if ((ber = kmfber_alloc_t(0)) != NULL) {
400*3089Swyllys 		/* copy data from the bv argument into BerElement */
401*3089Swyllys 		/* XXXmcs: had to cast unsigned long bv_len to long */
402*3089Swyllys 		if ((kmfber_write(ber, bv->bv_val, bv->bv_len, 0)) !=
403*3089Swyllys 			(ber_slen_t)bv->bv_len) {
404*3089Swyllys 			kmfber_free(ber, 1);
405*3089Swyllys 			return (NULL);
406*3089Swyllys 		}
407*3089Swyllys 	}
408*3089Swyllys 	/*
409*3089Swyllys 	 * reset ber_ptr back to the beginning of buffer so that this new
410*3089Swyllys 	 * and initialized ber element can be READ
411*3089Swyllys 	 */
412*3089Swyllys 	kmfber_reset(ber, 1);
413*3089Swyllys 
414*3089Swyllys 	/*
415*3089Swyllys 	 * return a ptr to a new BerElement containing a copy of the data
416*3089Swyllys 	 * in the bv argument or a null pointer on error
417*3089Swyllys 	 */
418*3089Swyllys 	return (ber);
419*3089Swyllys }
420