xref: /illumos-gate/usr/src/lib/libkmf/ber_der/common/io.c (revision de673234)
199ebb4caSwyllys /*
299ebb4caSwyllys  * -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
399ebb4caSwyllys  *
499ebb4caSwyllys  * The contents of this file are subject to the Netscape Public License
599ebb4caSwyllys  * Version 1.0 (the "NPL"); you may not use this file except in
699ebb4caSwyllys  * compliance with the NPL.  You may obtain a copy of the NPL at
799ebb4caSwyllys  * http://www.mozilla.org/NPL/
899ebb4caSwyllys  *
999ebb4caSwyllys  * Software distributed under the NPL is distributed on an "AS IS" basis,
1099ebb4caSwyllys  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
1199ebb4caSwyllys  * for the specific language governing rights and limitations under the
1299ebb4caSwyllys  * NPL.
1399ebb4caSwyllys  *
1499ebb4caSwyllys  * The Initial Developer of this code under the NPL is Netscape
1599ebb4caSwyllys  * Communications Corporation.  Portions created by Netscape are
1699ebb4caSwyllys  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
1799ebb4caSwyllys  * Reserved.
1899ebb4caSwyllys  */
1999ebb4caSwyllys 
2099ebb4caSwyllys /*
2199ebb4caSwyllys  * Copyright (c) 1990 Regents of the University of Michigan.
2299ebb4caSwyllys  * All rights reserved.
2399ebb4caSwyllys  *
2499ebb4caSwyllys  * Redistribution and use in source and binary forms are permitted
2599ebb4caSwyllys  * provided that this notice is preserved and that due credit is given
2699ebb4caSwyllys  * to the University of Michigan at Ann Arbor. The name of the University
2799ebb4caSwyllys  * may not be used to endorse or promote products derived from this
2899ebb4caSwyllys  * software without specific prior written permission. This software
2999ebb4caSwyllys  * is provided ``as is'' without express or implied warranty.
3099ebb4caSwyllys  */
3199ebb4caSwyllys /*
3256664548SWyllys Ingersoll  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
3399ebb4caSwyllys  * Use is subject to license terms.
3499ebb4caSwyllys  */
3599ebb4caSwyllys 
3699ebb4caSwyllys #include <stdlib.h>
3799ebb4caSwyllys #include <ber_der.h>
3899ebb4caSwyllys #include "kmfber_int.h"
3999ebb4caSwyllys 
4099ebb4caSwyllys #define	EXBUFSIZ	1024
4199ebb4caSwyllys 
4299ebb4caSwyllys /*
4399ebb4caSwyllys  * Note: kmfber_read() only uses the ber_end and ber_ptr elements of ber.
4499ebb4caSwyllys  * Functions like kmfber_get_tag(), kmfber_skip_tag, and kmfber_peek_tag()
4599ebb4caSwyllys  * rely on that fact, so if this code is changed to use any additional
4699ebb4caSwyllys  * elements of the ber structure, those functions will need to be changed
4799ebb4caSwyllys  * as well.
4899ebb4caSwyllys  */
4999ebb4caSwyllys ber_int_t
kmfber_read(BerElement * ber,char * buf,ber_len_t len)5099ebb4caSwyllys kmfber_read(BerElement *ber, char *buf, ber_len_t len)
5199ebb4caSwyllys {
5299ebb4caSwyllys 	size_t	actuallen;
5399ebb4caSwyllys 	size_t	nleft;
5499ebb4caSwyllys 
5599ebb4caSwyllys 	nleft = ber->ber_end - ber->ber_ptr;
5699ebb4caSwyllys 	actuallen = nleft < len ? nleft : len;
5799ebb4caSwyllys 
5899ebb4caSwyllys 	(void) memmove(buf, ber->ber_ptr, (size_t)actuallen);
5999ebb4caSwyllys 
6099ebb4caSwyllys 	ber->ber_ptr += actuallen;
6199ebb4caSwyllys 
6299ebb4caSwyllys 	return ((ber_int_t)actuallen);
6399ebb4caSwyllys }
6499ebb4caSwyllys 
6599ebb4caSwyllys /*
6699ebb4caSwyllys  * enlarge the ber buffer.
6799ebb4caSwyllys  * return 0 on success, -1 on error.
6899ebb4caSwyllys  */
6956664548SWyllys Ingersoll int
kmfber_realloc(BerElement * ber,ber_len_t len)7099ebb4caSwyllys kmfber_realloc(BerElement *ber, ber_len_t len)
7199ebb4caSwyllys {
7299ebb4caSwyllys 	ber_uint_t	need, have, total;
7399ebb4caSwyllys 	size_t		have_bytes;
7499ebb4caSwyllys 	Seqorset	*s;
7599ebb4caSwyllys 	size_t		off;
7699ebb4caSwyllys 	char		*oldbuf;
7799ebb4caSwyllys 
7899ebb4caSwyllys 	have_bytes = ber->ber_end - ber->ber_buf;
7999ebb4caSwyllys 	have = have_bytes / EXBUFSIZ;
8099ebb4caSwyllys 	need = (len < EXBUFSIZ ? 1 : (len + (EXBUFSIZ - 1)) / EXBUFSIZ);
8199ebb4caSwyllys 	total = have * EXBUFSIZ + need * EXBUFSIZ;
8299ebb4caSwyllys 
8399ebb4caSwyllys 	oldbuf = ber->ber_buf;
8499ebb4caSwyllys 
8599ebb4caSwyllys 	if (ber->ber_buf == NULL) {
8699ebb4caSwyllys 		if ((ber->ber_buf = (char *)malloc((size_t)total))
8799ebb4caSwyllys 		    == NULL) {
8899ebb4caSwyllys 			return (-1);
8999ebb4caSwyllys 		}
9099ebb4caSwyllys 		ber->ber_flags &= ~KMFBER_FLAG_NO_FREE_BUFFER;
9199ebb4caSwyllys 	} else {
9299ebb4caSwyllys 		if (ber->ber_flags & KMFBER_FLAG_NO_FREE_BUFFER) {
9399ebb4caSwyllys 			/* transition to malloc'd buffer */
9499ebb4caSwyllys 			if ((ber->ber_buf = (char *)malloc(
9599ebb4caSwyllys 			    (size_t)total)) == NULL) {
9699ebb4caSwyllys 				return (-1);
9799ebb4caSwyllys 			}
9899ebb4caSwyllys 			ber->ber_flags &= ~KMFBER_FLAG_NO_FREE_BUFFER;
99*de673234SWyllys Ingersoll 
10099ebb4caSwyllys 			/* copy existing data into new malloc'd buffer */
10199ebb4caSwyllys 			(void) memmove(ber->ber_buf, oldbuf, have_bytes);
10299ebb4caSwyllys 		} else {
10399ebb4caSwyllys 			if ((ber->ber_buf = (char *)realloc(
104*de673234SWyllys Ingersoll 			    oldbuf, (size_t)total)) == NULL) {
105*de673234SWyllys Ingersoll 				free(oldbuf);
10699ebb4caSwyllys 				return (-1);
10799ebb4caSwyllys 			}
10899ebb4caSwyllys 		}
10999ebb4caSwyllys 	}
11099ebb4caSwyllys 
11199ebb4caSwyllys 	ber->ber_end = ber->ber_buf + total;
11299ebb4caSwyllys 
11399ebb4caSwyllys 	/*
11499ebb4caSwyllys 	 * If the stinking thing was moved, we need to go through and
11599ebb4caSwyllys 	 * reset all the sos and ber pointers.  Offsets would've been
11699ebb4caSwyllys 	 * a better idea... oh well.
11799ebb4caSwyllys 	 */
11899ebb4caSwyllys 	if (ber->ber_buf != oldbuf) {
11999ebb4caSwyllys 		ber->ber_ptr = ber->ber_buf + (ber->ber_ptr - oldbuf);
12099ebb4caSwyllys 
12199ebb4caSwyllys 		for (s = ber->ber_sos; s != NULLSEQORSET; s = s->sos_next) {
12299ebb4caSwyllys 			off = s->sos_first - oldbuf;
12399ebb4caSwyllys 			s->sos_first = ber->ber_buf + off;
12499ebb4caSwyllys 
12599ebb4caSwyllys 			off = s->sos_ptr - oldbuf;
12699ebb4caSwyllys 			s->sos_ptr = ber->ber_buf + off;
12799ebb4caSwyllys 		}
12899ebb4caSwyllys 	}
12999ebb4caSwyllys 
13099ebb4caSwyllys 	return (0);
13199ebb4caSwyllys }
13299ebb4caSwyllys 
13399ebb4caSwyllys /*
13499ebb4caSwyllys  * returns "len" on success and -1 on failure.
13599ebb4caSwyllys  */
13699ebb4caSwyllys ber_int_t
kmfber_write(BerElement * ber,char * buf,ber_len_t len,int nosos)13799ebb4caSwyllys kmfber_write(BerElement *ber, char *buf, ber_len_t len, int nosos)
13899ebb4caSwyllys {
13999ebb4caSwyllys 	if (nosos || ber->ber_sos == NULL) {
14099ebb4caSwyllys 		if (ber->ber_ptr + len > ber->ber_end) {
14199ebb4caSwyllys 			if (kmfber_realloc(ber, len) != 0)
14299ebb4caSwyllys 				return (-1);
14399ebb4caSwyllys 		}
14499ebb4caSwyllys 		(void) memmove(ber->ber_ptr, buf, (size_t)len);
14599ebb4caSwyllys 		ber->ber_ptr += len;
14699ebb4caSwyllys 		return (len);
14799ebb4caSwyllys 	} else {
14899ebb4caSwyllys 		if (ber->ber_sos->sos_ptr + len > ber->ber_end) {
14999ebb4caSwyllys 			if (kmfber_realloc(ber, len) != 0)
15099ebb4caSwyllys 				return (-1);
15199ebb4caSwyllys 		}
15299ebb4caSwyllys 		(void) memmove(ber->ber_sos->sos_ptr, buf, (size_t)len);
15399ebb4caSwyllys 		ber->ber_sos->sos_ptr += len;
15499ebb4caSwyllys 		ber->ber_sos->sos_clen += len;
15599ebb4caSwyllys 		return (len);
15699ebb4caSwyllys 	}
15799ebb4caSwyllys }
15899ebb4caSwyllys 
15999ebb4caSwyllys void
kmfber_free(BerElement * ber,int freebuf)16099ebb4caSwyllys kmfber_free(BerElement *ber, int freebuf)
16199ebb4caSwyllys {
16299ebb4caSwyllys 	if (ber != NULL) {
16356664548SWyllys Ingersoll 		if (freebuf &&
16456664548SWyllys Ingersoll 		    !(ber->ber_flags & KMFBER_FLAG_NO_FREE_BUFFER))
16556664548SWyllys Ingersoll 			free(ber->ber_buf);
16656664548SWyllys Ingersoll 		free((char *)ber);
16799ebb4caSwyllys 	}
16899ebb4caSwyllys }
16999ebb4caSwyllys 
17099ebb4caSwyllys /* we pre-allocate a buffer to save the extra malloc later */
17199ebb4caSwyllys BerElement *
kmfber_alloc_t(int options)17299ebb4caSwyllys kmfber_alloc_t(int options)
17399ebb4caSwyllys {
17499ebb4caSwyllys 	BerElement	*ber;
17599ebb4caSwyllys 
17699ebb4caSwyllys 	if ((ber = (BerElement*)calloc(1,
17799ebb4caSwyllys 	    sizeof (struct berelement) + EXBUFSIZ)) == NULL) {
17899ebb4caSwyllys 		return (NULL);
17999ebb4caSwyllys 	}
18099ebb4caSwyllys 
18199ebb4caSwyllys 	ber->ber_tag = KMFBER_DEFAULT;
18299ebb4caSwyllys 	ber->ber_options = options;
18399ebb4caSwyllys 	ber->ber_buf = (char *)ber + sizeof (struct berelement);
18499ebb4caSwyllys 	ber->ber_ptr = ber->ber_buf;
18599ebb4caSwyllys 	ber->ber_end = ber->ber_buf + EXBUFSIZ;
18699ebb4caSwyllys 	ber->ber_flags = KMFBER_FLAG_NO_FREE_BUFFER;
18799ebb4caSwyllys 
18899ebb4caSwyllys 	return (ber);
18999ebb4caSwyllys }
19099ebb4caSwyllys 
19199ebb4caSwyllys 
19299ebb4caSwyllys BerElement *
kmfber_alloc()19399ebb4caSwyllys kmfber_alloc()
19499ebb4caSwyllys {
19599ebb4caSwyllys 	return (kmfber_alloc_t(0));
19699ebb4caSwyllys }
19799ebb4caSwyllys 
19899ebb4caSwyllys BerElement *
kmfder_alloc()19999ebb4caSwyllys kmfder_alloc()
20099ebb4caSwyllys {
20199ebb4caSwyllys 	return (kmfber_alloc_t(KMFBER_OPT_USE_DER));
20299ebb4caSwyllys }
20399ebb4caSwyllys 
20499ebb4caSwyllys BerElement *
kmfber_dup(BerElement * ber)20599ebb4caSwyllys kmfber_dup(BerElement *ber)
20699ebb4caSwyllys {
20799ebb4caSwyllys 	BerElement	*new;
20899ebb4caSwyllys 
20999ebb4caSwyllys 	if ((new = kmfber_alloc()) == NULL)
21099ebb4caSwyllys 		return (NULL);
21199ebb4caSwyllys 
21299ebb4caSwyllys 	*new = *ber;
21399ebb4caSwyllys 
21499ebb4caSwyllys 	return (new);
21599ebb4caSwyllys }
21699ebb4caSwyllys 
21799ebb4caSwyllys 
21899ebb4caSwyllys void
ber_init_w_nullchar(BerElement * ber,int options)21999ebb4caSwyllys ber_init_w_nullchar(BerElement *ber, int options)
22099ebb4caSwyllys {
22199ebb4caSwyllys 	(void) memset((char *)ber, '\0', sizeof (struct berelement));
22299ebb4caSwyllys 	ber->ber_tag = KMFBER_DEFAULT;
22399ebb4caSwyllys 
22499ebb4caSwyllys 	ber->ber_options = options;
22599ebb4caSwyllys }
22699ebb4caSwyllys 
22799ebb4caSwyllys 
22899ebb4caSwyllys void
kmfber_reset(BerElement * ber,int was_writing)22999ebb4caSwyllys kmfber_reset(BerElement *ber, int was_writing)
23099ebb4caSwyllys {
23199ebb4caSwyllys 	if (was_writing) {
23299ebb4caSwyllys 		ber->ber_end = ber->ber_ptr;
23399ebb4caSwyllys 		ber->ber_ptr = ber->ber_buf;
23499ebb4caSwyllys 	} else {
23599ebb4caSwyllys 		ber->ber_ptr = ber->ber_end;
23699ebb4caSwyllys 	}
23799ebb4caSwyllys 
23899ebb4caSwyllys 	ber->ber_rwptr = NULL;
23999ebb4caSwyllys }
24099ebb4caSwyllys 
24199ebb4caSwyllys 
24299ebb4caSwyllys #ifdef KMFBER_DEBUG
24399ebb4caSwyllys 
24499ebb4caSwyllys void
ber_dump(BerElement * ber,int inout)24599ebb4caSwyllys ber_dump(BerElement *ber, int inout)
24699ebb4caSwyllys {
24799ebb4caSwyllys 	char msg[128];
24899ebb4caSwyllys 	sprintf(msg, "ber_dump: buf 0x%lx, ptr 0x%lx, rwptr 0x%lx, end 0x%lx\n",
24999ebb4caSwyllys 	    ber->ber_buf, ber->ber_ptr, ber->ber_rwptr, ber->ber_end);
25099ebb4caSwyllys 	ber_err_print(msg);
25199ebb4caSwyllys 	if (inout == 1) {
25299ebb4caSwyllys 		sprintf(msg, "          current len %ld, contents:\n",
25399ebb4caSwyllys 		    ber->ber_end - ber->ber_ptr);
25499ebb4caSwyllys 		ber_err_print(msg);
25599ebb4caSwyllys 		lber_bprint(ber->ber_ptr, ber->ber_end - ber->ber_ptr);
25699ebb4caSwyllys 	} else {
25799ebb4caSwyllys 		sprintf(msg, "          current len %ld, contents:\n",
25899ebb4caSwyllys 		    ber->ber_ptr - ber->ber_buf);
25999ebb4caSwyllys 		ber_err_print(msg);
26099ebb4caSwyllys 		lber_bprint(ber->ber_buf, ber->ber_ptr - ber->ber_buf);
26199ebb4caSwyllys 	}
26299ebb4caSwyllys }
26399ebb4caSwyllys 
26499ebb4caSwyllys void
ber_sos_dump(Seqorset * sos)26599ebb4caSwyllys ber_sos_dump(Seqorset *sos)
26699ebb4caSwyllys {
26799ebb4caSwyllys 	char msg[80];
26899ebb4caSwyllys 	ber_err_print("*** sos dump ***\n");
26999ebb4caSwyllys 	while (sos != NULLSEQORSET) {
27099ebb4caSwyllys 		sprintf(msg, "ber_sos_dump: clen %ld first 0x%lx ptr 0x%lx\n",
27199ebb4caSwyllys 		    sos->sos_clen, sos->sos_first, sos->sos_ptr);
27299ebb4caSwyllys 		ber_err_print(msg);
27399ebb4caSwyllys 		sprintf(msg, "              current len %ld contents:\n",
27499ebb4caSwyllys 		    sos->sos_ptr - sos->sos_first);
27599ebb4caSwyllys 		ber_err_print(msg);
27699ebb4caSwyllys 		lber_bprint(sos->sos_first, sos->sos_ptr - sos->sos_first);
27799ebb4caSwyllys 
27899ebb4caSwyllys 		sos = sos->sos_next;
27999ebb4caSwyllys 	}
28099ebb4caSwyllys 	ber_err_print("*** end dump ***\n");
28199ebb4caSwyllys }
28299ebb4caSwyllys 
28399ebb4caSwyllys #endif
28499ebb4caSwyllys 
28599ebb4caSwyllys /* new dboreham code below: */
28699ebb4caSwyllys struct byte_buffer  {
28799ebb4caSwyllys 	unsigned char *p;
28899ebb4caSwyllys 	int offset;
28999ebb4caSwyllys 	int length;
29099ebb4caSwyllys };
29199ebb4caSwyllys typedef struct byte_buffer byte_buffer;
29299ebb4caSwyllys 
29399ebb4caSwyllys /*
29499ebb4caSwyllys  * The kmfber_flatten routine allocates a struct berval whose contents
29599ebb4caSwyllys  * are a BER encoding taken from the ber argument. The bvPtr pointer
29699ebb4caSwyllys  * points to the returned berval, which must be freed using
29799ebb4caSwyllys  * kmfber_bvfree().  This routine returns 0 on success and -1 on error.
29899ebb4caSwyllys  * The use of kmfber_flatten on a BerElement in which all '{' and '}'
29999ebb4caSwyllys  * format modifiers have not been properly matched can result in a
30099ebb4caSwyllys  * berval whose contents are not a valid BER encoding.
30199ebb4caSwyllys  * Note that the ber_ptr is not modified.
30299ebb4caSwyllys  */
30399ebb4caSwyllys int
kmfber_flatten(BerElement * ber,struct berval ** bvPtr)30499ebb4caSwyllys kmfber_flatten(BerElement *ber, struct berval **bvPtr)
30599ebb4caSwyllys {
30699ebb4caSwyllys 	struct berval *new;
30799ebb4caSwyllys 	ber_len_t len;
30899ebb4caSwyllys 
30999ebb4caSwyllys 	/* allocate a struct berval */
31099ebb4caSwyllys 	new = (struct berval *)malloc((size_t)(sizeof (struct berval)));
31199ebb4caSwyllys 	if (new == NULL) {
31299ebb4caSwyllys 		return (-1);
31399ebb4caSwyllys 	}
31499ebb4caSwyllys 	(void) memset(new, 0, sizeof (struct berval));
31599ebb4caSwyllys 
31699ebb4caSwyllys 	/*
31799ebb4caSwyllys 	 * Copy everything from the BerElement's ber_buf to ber_ptr
31899ebb4caSwyllys 	 * into the berval structure.
31999ebb4caSwyllys 	 */
32099ebb4caSwyllys 	if (ber == NULL) {
32199ebb4caSwyllys 		new->bv_val = NULL;
32299ebb4caSwyllys 		new->bv_len = 0;
32399ebb4caSwyllys 	} else {
32499ebb4caSwyllys 		len = ber->ber_ptr - ber->ber_buf;
32599ebb4caSwyllys 		new->bv_val = (char *)malloc((size_t)(len + 1));
32699ebb4caSwyllys 		if (new->bv_val == NULL) {
32799ebb4caSwyllys 			kmfber_bvfree(new);
32899ebb4caSwyllys 			return (-1);
32999ebb4caSwyllys 		}
33099ebb4caSwyllys 		(void) memmove(new->bv_val, ber->ber_buf, (size_t)len);
33199ebb4caSwyllys 		new->bv_val[len] = '\0';
33299ebb4caSwyllys 		new->bv_len = len;
33399ebb4caSwyllys 	}
33499ebb4caSwyllys 
33599ebb4caSwyllys 	/* set bvPtr pointer to point to the returned berval */
33699ebb4caSwyllys 	*bvPtr = new;
33799ebb4caSwyllys 
33899ebb4caSwyllys 	return (0);
33999ebb4caSwyllys }
34099ebb4caSwyllys 
34199ebb4caSwyllys BerElement *
kmfder_init(const struct berval * bv)34299ebb4caSwyllys kmfder_init(const struct berval *bv)
34399ebb4caSwyllys {
34499ebb4caSwyllys 	BerElement *ber;
34599ebb4caSwyllys 
34699ebb4caSwyllys 	/* construct BerElement */
34799ebb4caSwyllys 	if ((ber = kmfber_alloc_t(KMFBER_OPT_USE_DER)) != NULL) {
34899ebb4caSwyllys 		/* copy data from the bv argument into BerElement */
34999ebb4caSwyllys 		/* XXXmcs: had to cast unsigned long bv_len to long */
35099ebb4caSwyllys 		if ((kmfber_write(ber, bv->bv_val, bv->bv_len, 0)) !=
35156664548SWyllys Ingersoll 		    (ber_slen_t)bv->bv_len) {
35299ebb4caSwyllys 			kmfber_free(ber, 1);
35399ebb4caSwyllys 			return (NULL);
35499ebb4caSwyllys 		}
35599ebb4caSwyllys 	}
35699ebb4caSwyllys 	/*
35799ebb4caSwyllys 	 * reset ber_ptr back to the beginning of buffer so that this new
35899ebb4caSwyllys 	 * and initialized ber element can be READ
35999ebb4caSwyllys 	 */
36099ebb4caSwyllys 	kmfber_reset(ber, 1);
36199ebb4caSwyllys 
36299ebb4caSwyllys 	/*
36399ebb4caSwyllys 	 * return a ptr to a new BerElement containing a copy of the data
36499ebb4caSwyllys 	 * in the bv argument or a null pointer on error
36599ebb4caSwyllys 	 */
36699ebb4caSwyllys 	return (ber);
36799ebb4caSwyllys }
36899ebb4caSwyllys 
36999ebb4caSwyllys BerElement *
kmfber_init(const struct berval * bv)37099ebb4caSwyllys kmfber_init(const struct berval *bv)
37199ebb4caSwyllys {
37299ebb4caSwyllys 	BerElement *ber;
37399ebb4caSwyllys 
37499ebb4caSwyllys 	/* construct BerElement */
37599ebb4caSwyllys 	if ((ber = kmfber_alloc_t(0)) != NULL) {
37699ebb4caSwyllys 		/* copy data from the bv argument into BerElement */
37799ebb4caSwyllys 		/* XXXmcs: had to cast unsigned long bv_len to long */
37899ebb4caSwyllys 		if ((kmfber_write(ber, bv->bv_val, bv->bv_len, 0)) !=
37956664548SWyllys Ingersoll 		    (ber_slen_t)bv->bv_len) {
38099ebb4caSwyllys 			kmfber_free(ber, 1);
38199ebb4caSwyllys 			return (NULL);
38299ebb4caSwyllys 		}
38399ebb4caSwyllys 	}
38499ebb4caSwyllys 	/*
38599ebb4caSwyllys 	 * reset ber_ptr back to the beginning of buffer so that this new
38699ebb4caSwyllys 	 * and initialized ber element can be READ
38799ebb4caSwyllys 	 */
38899ebb4caSwyllys 	kmfber_reset(ber, 1);
38999ebb4caSwyllys 
39099ebb4caSwyllys 	/*
39199ebb4caSwyllys 	 * return a ptr to a new BerElement containing a copy of the data
39299ebb4caSwyllys 	 * in the bv argument or a null pointer on error
39399ebb4caSwyllys 	 */
39499ebb4caSwyllys 	return (ber);
39599ebb4caSwyllys }
396