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 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 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 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 16099ebb4caSwyllys kmfber_free(BerElement *ber, int freebuf) 16199ebb4caSwyllys { 16299ebb4caSwyllys if (ber != NULL) { 16399ebb4caSwyllys if (freebuf && 16456664548SWyllys Ingersoll !(ber->ber_flags & KMFBER_FLAG_NO_FREE_BUFFER)) 16599ebb4caSwyllys free(ber->ber_buf); 16699ebb4caSwyllys free((char *)ber); 16799ebb4caSwyllys } 16899ebb4caSwyllys } 16999ebb4caSwyllys 17099ebb4caSwyllys /* we pre-allocate a buffer to save the extra malloc later */ 17199ebb4caSwyllys BerElement * 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 * 19399ebb4caSwyllys kmfber_alloc() 19499ebb4caSwyllys { 19599ebb4caSwyllys return (kmfber_alloc_t(0)); 19699ebb4caSwyllys } 19799ebb4caSwyllys 19899ebb4caSwyllys BerElement * 19999ebb4caSwyllys kmfder_alloc() 20099ebb4caSwyllys { 20199ebb4caSwyllys return (kmfber_alloc_t(KMFBER_OPT_USE_DER)); 20299ebb4caSwyllys } 20399ebb4caSwyllys 20499ebb4caSwyllys BerElement * 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 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 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 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 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 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 * 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)) != 35199ebb4caSwyllys (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 * 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)) != 37999ebb4caSwyllys (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