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