13089Swyllys /*
23089Swyllys * -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
33089Swyllys *
43089Swyllys * The contents of this file are subject to the Netscape Public License
53089Swyllys * Version 1.0 (the "NPL"); you may not use this file except in
63089Swyllys * compliance with the NPL. You may obtain a copy of the NPL at
73089Swyllys * http://www.mozilla.org/NPL/
83089Swyllys *
93089Swyllys * Software distributed under the NPL is distributed on an "AS IS" basis,
103089Swyllys * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
113089Swyllys * for the specific language governing rights and limitations under the
123089Swyllys * NPL.
133089Swyllys *
143089Swyllys * The Initial Developer of this code under the NPL is Netscape
153089Swyllys * Communications Corporation. Portions created by Netscape are
163089Swyllys * Copyright (C) 1998 Netscape Communications Corporation. All Rights
173089Swyllys * Reserved.
183089Swyllys */
193089Swyllys
203089Swyllys /*
213089Swyllys * Copyright (c) 1990 Regents of the University of Michigan.
223089Swyllys * All rights reserved.
233089Swyllys *
243089Swyllys * Redistribution and use in source and binary forms are permitted
253089Swyllys * provided that this notice is preserved and that due credit is given
263089Swyllys * to the University of Michigan at Ann Arbor. The name of the University
273089Swyllys * may not be used to endorse or promote products derived from this
283089Swyllys * software without specific prior written permission. This software
293089Swyllys * is provided ``as is'' without express or implied warranty.
303089Swyllys */
313089Swyllys /*
3210818Swyllys.ingersoll@sun.com * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
333089Swyllys * Use is subject to license terms.
343089Swyllys */
353089Swyllys
363089Swyllys #include <stdlib.h>
373089Swyllys #include <ber_der.h>
383089Swyllys #include "kmfber_int.h"
393089Swyllys
403089Swyllys #define EXBUFSIZ 1024
413089Swyllys
423089Swyllys /*
433089Swyllys * Note: kmfber_read() only uses the ber_end and ber_ptr elements of ber.
443089Swyllys * Functions like kmfber_get_tag(), kmfber_skip_tag, and kmfber_peek_tag()
453089Swyllys * rely on that fact, so if this code is changed to use any additional
463089Swyllys * elements of the ber structure, those functions will need to be changed
473089Swyllys * as well.
483089Swyllys */
493089Swyllys ber_int_t
kmfber_read(BerElement * ber,char * buf,ber_len_t len)503089Swyllys kmfber_read(BerElement *ber, char *buf, ber_len_t len)
513089Swyllys {
523089Swyllys size_t actuallen;
533089Swyllys size_t nleft;
543089Swyllys
553089Swyllys nleft = ber->ber_end - ber->ber_ptr;
563089Swyllys actuallen = nleft < len ? nleft : len;
573089Swyllys
583089Swyllys (void) memmove(buf, ber->ber_ptr, (size_t)actuallen);
593089Swyllys
603089Swyllys ber->ber_ptr += actuallen;
613089Swyllys
623089Swyllys return ((ber_int_t)actuallen);
633089Swyllys }
643089Swyllys
653089Swyllys /*
663089Swyllys * enlarge the ber buffer.
673089Swyllys * return 0 on success, -1 on error.
683089Swyllys */
6910818Swyllys.ingersoll@sun.com int
kmfber_realloc(BerElement * ber,ber_len_t len)703089Swyllys kmfber_realloc(BerElement *ber, ber_len_t len)
713089Swyllys {
723089Swyllys ber_uint_t need, have, total;
733089Swyllys size_t have_bytes;
743089Swyllys Seqorset *s;
753089Swyllys size_t off;
763089Swyllys char *oldbuf;
773089Swyllys
783089Swyllys have_bytes = ber->ber_end - ber->ber_buf;
793089Swyllys have = have_bytes / EXBUFSIZ;
803089Swyllys need = (len < EXBUFSIZ ? 1 : (len + (EXBUFSIZ - 1)) / EXBUFSIZ);
813089Swyllys total = have * EXBUFSIZ + need * EXBUFSIZ;
823089Swyllys
833089Swyllys oldbuf = ber->ber_buf;
843089Swyllys
853089Swyllys if (ber->ber_buf == NULL) {
863089Swyllys if ((ber->ber_buf = (char *)malloc((size_t)total))
873089Swyllys == NULL) {
883089Swyllys return (-1);
893089Swyllys }
903089Swyllys ber->ber_flags &= ~KMFBER_FLAG_NO_FREE_BUFFER;
913089Swyllys } else {
923089Swyllys if (ber->ber_flags & KMFBER_FLAG_NO_FREE_BUFFER) {
933089Swyllys /* transition to malloc'd buffer */
943089Swyllys if ((ber->ber_buf = (char *)malloc(
953089Swyllys (size_t)total)) == NULL) {
963089Swyllys return (-1);
973089Swyllys }
983089Swyllys ber->ber_flags &= ~KMFBER_FLAG_NO_FREE_BUFFER;
99*11221Swyllys.ingersoll@sun.com
1003089Swyllys /* copy existing data into new malloc'd buffer */
1013089Swyllys (void) memmove(ber->ber_buf, oldbuf, have_bytes);
1023089Swyllys } else {
1033089Swyllys if ((ber->ber_buf = (char *)realloc(
104*11221Swyllys.ingersoll@sun.com oldbuf, (size_t)total)) == NULL) {
105*11221Swyllys.ingersoll@sun.com free(oldbuf);
1063089Swyllys return (-1);
1073089Swyllys }
1083089Swyllys }
1093089Swyllys }
1103089Swyllys
1113089Swyllys ber->ber_end = ber->ber_buf + total;
1123089Swyllys
1133089Swyllys /*
1143089Swyllys * If the stinking thing was moved, we need to go through and
1153089Swyllys * reset all the sos and ber pointers. Offsets would've been
1163089Swyllys * a better idea... oh well.
1173089Swyllys */
1183089Swyllys if (ber->ber_buf != oldbuf) {
1193089Swyllys ber->ber_ptr = ber->ber_buf + (ber->ber_ptr - oldbuf);
1203089Swyllys
1213089Swyllys for (s = ber->ber_sos; s != NULLSEQORSET; s = s->sos_next) {
1223089Swyllys off = s->sos_first - oldbuf;
1233089Swyllys s->sos_first = ber->ber_buf + off;
1243089Swyllys
1253089Swyllys off = s->sos_ptr - oldbuf;
1263089Swyllys s->sos_ptr = ber->ber_buf + off;
1273089Swyllys }
1283089Swyllys }
1293089Swyllys
1303089Swyllys return (0);
1313089Swyllys }
1323089Swyllys
1333089Swyllys /*
1343089Swyllys * returns "len" on success and -1 on failure.
1353089Swyllys */
1363089Swyllys ber_int_t
kmfber_write(BerElement * ber,char * buf,ber_len_t len,int nosos)1373089Swyllys kmfber_write(BerElement *ber, char *buf, ber_len_t len, int nosos)
1383089Swyllys {
1393089Swyllys if (nosos || ber->ber_sos == NULL) {
1403089Swyllys if (ber->ber_ptr + len > ber->ber_end) {
1413089Swyllys if (kmfber_realloc(ber, len) != 0)
1423089Swyllys return (-1);
1433089Swyllys }
1443089Swyllys (void) memmove(ber->ber_ptr, buf, (size_t)len);
1453089Swyllys ber->ber_ptr += len;
1463089Swyllys return (len);
1473089Swyllys } else {
1483089Swyllys if (ber->ber_sos->sos_ptr + len > ber->ber_end) {
1493089Swyllys if (kmfber_realloc(ber, len) != 0)
1503089Swyllys return (-1);
1513089Swyllys }
1523089Swyllys (void) memmove(ber->ber_sos->sos_ptr, buf, (size_t)len);
1533089Swyllys ber->ber_sos->sos_ptr += len;
1543089Swyllys ber->ber_sos->sos_clen += len;
1553089Swyllys return (len);
1563089Swyllys }
1573089Swyllys }
1583089Swyllys
1593089Swyllys void
kmfber_free(BerElement * ber,int freebuf)1603089Swyllys kmfber_free(BerElement *ber, int freebuf)
1613089Swyllys {
1623089Swyllys if (ber != NULL) {
16310818Swyllys.ingersoll@sun.com if (freebuf &&
16410818Swyllys.ingersoll@sun.com !(ber->ber_flags & KMFBER_FLAG_NO_FREE_BUFFER))
16510818Swyllys.ingersoll@sun.com free(ber->ber_buf);
16610818Swyllys.ingersoll@sun.com free((char *)ber);
1673089Swyllys }
1683089Swyllys }
1693089Swyllys
1703089Swyllys /* we pre-allocate a buffer to save the extra malloc later */
1713089Swyllys BerElement *
kmfber_alloc_t(int options)1723089Swyllys kmfber_alloc_t(int options)
1733089Swyllys {
1743089Swyllys BerElement *ber;
1753089Swyllys
1763089Swyllys if ((ber = (BerElement*)calloc(1,
1773089Swyllys sizeof (struct berelement) + EXBUFSIZ)) == NULL) {
1783089Swyllys return (NULL);
1793089Swyllys }
1803089Swyllys
1813089Swyllys ber->ber_tag = KMFBER_DEFAULT;
1823089Swyllys ber->ber_options = options;
1833089Swyllys ber->ber_buf = (char *)ber + sizeof (struct berelement);
1843089Swyllys ber->ber_ptr = ber->ber_buf;
1853089Swyllys ber->ber_end = ber->ber_buf + EXBUFSIZ;
1863089Swyllys ber->ber_flags = KMFBER_FLAG_NO_FREE_BUFFER;
1873089Swyllys
1883089Swyllys return (ber);
1893089Swyllys }
1903089Swyllys
1913089Swyllys
1923089Swyllys BerElement *
kmfber_alloc()1933089Swyllys kmfber_alloc()
1943089Swyllys {
1953089Swyllys return (kmfber_alloc_t(0));
1963089Swyllys }
1973089Swyllys
1983089Swyllys BerElement *
kmfder_alloc()1993089Swyllys kmfder_alloc()
2003089Swyllys {
2013089Swyllys return (kmfber_alloc_t(KMFBER_OPT_USE_DER));
2023089Swyllys }
2033089Swyllys
2043089Swyllys BerElement *
kmfber_dup(BerElement * ber)2053089Swyllys kmfber_dup(BerElement *ber)
2063089Swyllys {
2073089Swyllys BerElement *new;
2083089Swyllys
2093089Swyllys if ((new = kmfber_alloc()) == NULL)
2103089Swyllys return (NULL);
2113089Swyllys
2123089Swyllys *new = *ber;
2133089Swyllys
2143089Swyllys return (new);
2153089Swyllys }
2163089Swyllys
2173089Swyllys
2183089Swyllys void
ber_init_w_nullchar(BerElement * ber,int options)2193089Swyllys ber_init_w_nullchar(BerElement *ber, int options)
2203089Swyllys {
2213089Swyllys (void) memset((char *)ber, '\0', sizeof (struct berelement));
2223089Swyllys ber->ber_tag = KMFBER_DEFAULT;
2233089Swyllys
2243089Swyllys ber->ber_options = options;
2253089Swyllys }
2263089Swyllys
2273089Swyllys
2283089Swyllys void
kmfber_reset(BerElement * ber,int was_writing)2293089Swyllys kmfber_reset(BerElement *ber, int was_writing)
2303089Swyllys {
2313089Swyllys if (was_writing) {
2323089Swyllys ber->ber_end = ber->ber_ptr;
2333089Swyllys ber->ber_ptr = ber->ber_buf;
2343089Swyllys } else {
2353089Swyllys ber->ber_ptr = ber->ber_end;
2363089Swyllys }
2373089Swyllys
2383089Swyllys ber->ber_rwptr = NULL;
2393089Swyllys }
2403089Swyllys
2413089Swyllys
2423089Swyllys #ifdef KMFBER_DEBUG
2433089Swyllys
2443089Swyllys void
ber_dump(BerElement * ber,int inout)2453089Swyllys ber_dump(BerElement *ber, int inout)
2463089Swyllys {
2473089Swyllys char msg[128];
2483089Swyllys sprintf(msg, "ber_dump: buf 0x%lx, ptr 0x%lx, rwptr 0x%lx, end 0x%lx\n",
2493089Swyllys ber->ber_buf, ber->ber_ptr, ber->ber_rwptr, ber->ber_end);
2503089Swyllys ber_err_print(msg);
2513089Swyllys if (inout == 1) {
2523089Swyllys sprintf(msg, " current len %ld, contents:\n",
2533089Swyllys ber->ber_end - ber->ber_ptr);
2543089Swyllys ber_err_print(msg);
2553089Swyllys lber_bprint(ber->ber_ptr, ber->ber_end - ber->ber_ptr);
2563089Swyllys } else {
2573089Swyllys sprintf(msg, " current len %ld, contents:\n",
2583089Swyllys ber->ber_ptr - ber->ber_buf);
2593089Swyllys ber_err_print(msg);
2603089Swyllys lber_bprint(ber->ber_buf, ber->ber_ptr - ber->ber_buf);
2613089Swyllys }
2623089Swyllys }
2633089Swyllys
2643089Swyllys void
ber_sos_dump(Seqorset * sos)2653089Swyllys ber_sos_dump(Seqorset *sos)
2663089Swyllys {
2673089Swyllys char msg[80];
2683089Swyllys ber_err_print("*** sos dump ***\n");
2693089Swyllys while (sos != NULLSEQORSET) {
2703089Swyllys sprintf(msg, "ber_sos_dump: clen %ld first 0x%lx ptr 0x%lx\n",
2713089Swyllys sos->sos_clen, sos->sos_first, sos->sos_ptr);
2723089Swyllys ber_err_print(msg);
2733089Swyllys sprintf(msg, " current len %ld contents:\n",
2743089Swyllys sos->sos_ptr - sos->sos_first);
2753089Swyllys ber_err_print(msg);
2763089Swyllys lber_bprint(sos->sos_first, sos->sos_ptr - sos->sos_first);
2773089Swyllys
2783089Swyllys sos = sos->sos_next;
2793089Swyllys }
2803089Swyllys ber_err_print("*** end dump ***\n");
2813089Swyllys }
2823089Swyllys
2833089Swyllys #endif
2843089Swyllys
2853089Swyllys /* new dboreham code below: */
2863089Swyllys struct byte_buffer {
2873089Swyllys unsigned char *p;
2883089Swyllys int offset;
2893089Swyllys int length;
2903089Swyllys };
2913089Swyllys typedef struct byte_buffer byte_buffer;
2923089Swyllys
2933089Swyllys /*
2943089Swyllys * The kmfber_flatten routine allocates a struct berval whose contents
2953089Swyllys * are a BER encoding taken from the ber argument. The bvPtr pointer
2963089Swyllys * points to the returned berval, which must be freed using
2973089Swyllys * kmfber_bvfree(). This routine returns 0 on success and -1 on error.
2983089Swyllys * The use of kmfber_flatten on a BerElement in which all '{' and '}'
2993089Swyllys * format modifiers have not been properly matched can result in a
3003089Swyllys * berval whose contents are not a valid BER encoding.
3013089Swyllys * Note that the ber_ptr is not modified.
3023089Swyllys */
3033089Swyllys int
kmfber_flatten(BerElement * ber,struct berval ** bvPtr)3043089Swyllys kmfber_flatten(BerElement *ber, struct berval **bvPtr)
3053089Swyllys {
3063089Swyllys struct berval *new;
3073089Swyllys ber_len_t len;
3083089Swyllys
3093089Swyllys /* allocate a struct berval */
3103089Swyllys new = (struct berval *)malloc((size_t)(sizeof (struct berval)));
3113089Swyllys if (new == NULL) {
3123089Swyllys return (-1);
3133089Swyllys }
3143089Swyllys (void) memset(new, 0, sizeof (struct berval));
3153089Swyllys
3163089Swyllys /*
3173089Swyllys * Copy everything from the BerElement's ber_buf to ber_ptr
3183089Swyllys * into the berval structure.
3193089Swyllys */
3203089Swyllys if (ber == NULL) {
3213089Swyllys new->bv_val = NULL;
3223089Swyllys new->bv_len = 0;
3233089Swyllys } else {
3243089Swyllys len = ber->ber_ptr - ber->ber_buf;
3253089Swyllys new->bv_val = (char *)malloc((size_t)(len + 1));
3263089Swyllys if (new->bv_val == NULL) {
3273089Swyllys kmfber_bvfree(new);
3283089Swyllys return (-1);
3293089Swyllys }
3303089Swyllys (void) memmove(new->bv_val, ber->ber_buf, (size_t)len);
3313089Swyllys new->bv_val[len] = '\0';
3323089Swyllys new->bv_len = len;
3333089Swyllys }
3343089Swyllys
3353089Swyllys /* set bvPtr pointer to point to the returned berval */
3363089Swyllys *bvPtr = new;
3373089Swyllys
3383089Swyllys return (0);
3393089Swyllys }
3403089Swyllys
3413089Swyllys BerElement *
kmfder_init(const struct berval * bv)3423089Swyllys kmfder_init(const struct berval *bv)
3433089Swyllys {
3443089Swyllys BerElement *ber;
3453089Swyllys
3463089Swyllys /* construct BerElement */
3473089Swyllys if ((ber = kmfber_alloc_t(KMFBER_OPT_USE_DER)) != NULL) {
3483089Swyllys /* copy data from the bv argument into BerElement */
3493089Swyllys /* XXXmcs: had to cast unsigned long bv_len to long */
3503089Swyllys if ((kmfber_write(ber, bv->bv_val, bv->bv_len, 0)) !=
35110818Swyllys.ingersoll@sun.com (ber_slen_t)bv->bv_len) {
3523089Swyllys kmfber_free(ber, 1);
3533089Swyllys return (NULL);
3543089Swyllys }
3553089Swyllys }
3563089Swyllys /*
3573089Swyllys * reset ber_ptr back to the beginning of buffer so that this new
3583089Swyllys * and initialized ber element can be READ
3593089Swyllys */
3603089Swyllys kmfber_reset(ber, 1);
3613089Swyllys
3623089Swyllys /*
3633089Swyllys * return a ptr to a new BerElement containing a copy of the data
3643089Swyllys * in the bv argument or a null pointer on error
3653089Swyllys */
3663089Swyllys return (ber);
3673089Swyllys }
3683089Swyllys
3693089Swyllys BerElement *
kmfber_init(const struct berval * bv)3703089Swyllys kmfber_init(const struct berval *bv)
3713089Swyllys {
3723089Swyllys BerElement *ber;
3733089Swyllys
3743089Swyllys /* construct BerElement */
3753089Swyllys if ((ber = kmfber_alloc_t(0)) != NULL) {
3763089Swyllys /* copy data from the bv argument into BerElement */
3773089Swyllys /* XXXmcs: had to cast unsigned long bv_len to long */
3783089Swyllys if ((kmfber_write(ber, bv->bv_val, bv->bv_len, 0)) !=
37910818Swyllys.ingersoll@sun.com (ber_slen_t)bv->bv_len) {
3803089Swyllys kmfber_free(ber, 1);
3813089Swyllys return (NULL);
3823089Swyllys }
3833089Swyllys }
3843089Swyllys /*
3853089Swyllys * reset ber_ptr back to the beginning of buffer so that this new
3863089Swyllys * and initialized ber element can be READ
3873089Swyllys */
3883089Swyllys kmfber_reset(ber, 1);
3893089Swyllys
3903089Swyllys /*
3913089Swyllys * return a ptr to a new BerElement containing a copy of the data
3923089Swyllys * in the bv argument or a null pointer on error
3933089Swyllys */
3943089Swyllys return (ber);
3953089Swyllys }
396