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 /* 32*10818Swyllys.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 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 */ 69*10818Swyllys.ingersoll@sun.com int 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; 77*10818Swyllys.ingersoll@sun.com boolean_t freeold = B_FALSE; 783089Swyllys 793089Swyllys have_bytes = ber->ber_end - ber->ber_buf; 803089Swyllys have = have_bytes / EXBUFSIZ; 813089Swyllys need = (len < EXBUFSIZ ? 1 : (len + (EXBUFSIZ - 1)) / EXBUFSIZ); 823089Swyllys total = have * EXBUFSIZ + need * EXBUFSIZ; 833089Swyllys 843089Swyllys oldbuf = ber->ber_buf; 853089Swyllys 863089Swyllys if (ber->ber_buf == NULL) { 873089Swyllys if ((ber->ber_buf = (char *)malloc((size_t)total)) 883089Swyllys == NULL) { 893089Swyllys return (-1); 903089Swyllys } 913089Swyllys ber->ber_flags &= ~KMFBER_FLAG_NO_FREE_BUFFER; 923089Swyllys } else { 933089Swyllys if (ber->ber_flags & KMFBER_FLAG_NO_FREE_BUFFER) { 943089Swyllys /* transition to malloc'd buffer */ 953089Swyllys if ((ber->ber_buf = (char *)malloc( 963089Swyllys (size_t)total)) == NULL) { 97*10818Swyllys.ingersoll@sun.com free(oldbuf); 983089Swyllys return (-1); 993089Swyllys } 1003089Swyllys ber->ber_flags &= ~KMFBER_FLAG_NO_FREE_BUFFER; 1013089Swyllys /* copy existing data into new malloc'd buffer */ 1023089Swyllys (void) memmove(ber->ber_buf, oldbuf, have_bytes); 103*10818Swyllys.ingersoll@sun.com freeold = B_TRUE; 1043089Swyllys } else { 1053089Swyllys if ((ber->ber_buf = (char *)realloc( 1063089Swyllys ber->ber_buf, (size_t)total)) == NULL) { 1073089Swyllys return (-1); 1083089Swyllys } 109*10818Swyllys.ingersoll@sun.com freeold = B_FALSE; /* it was just realloced */ 1103089Swyllys } 1113089Swyllys } 1123089Swyllys 1133089Swyllys ber->ber_end = ber->ber_buf + total; 1143089Swyllys 1153089Swyllys /* 1163089Swyllys * If the stinking thing was moved, we need to go through and 1173089Swyllys * reset all the sos and ber pointers. Offsets would've been 1183089Swyllys * a better idea... oh well. 1193089Swyllys */ 1203089Swyllys if (ber->ber_buf != oldbuf) { 1213089Swyllys ber->ber_ptr = ber->ber_buf + (ber->ber_ptr - oldbuf); 1223089Swyllys 1233089Swyllys for (s = ber->ber_sos; s != NULLSEQORSET; s = s->sos_next) { 1243089Swyllys off = s->sos_first - oldbuf; 1253089Swyllys s->sos_first = ber->ber_buf + off; 1263089Swyllys 1273089Swyllys off = s->sos_ptr - oldbuf; 1283089Swyllys s->sos_ptr = ber->ber_buf + off; 1293089Swyllys } 1303089Swyllys } 131*10818Swyllys.ingersoll@sun.com if (freeold && oldbuf != NULL) 132*10818Swyllys.ingersoll@sun.com free(oldbuf); 1333089Swyllys 1343089Swyllys return (0); 1353089Swyllys } 1363089Swyllys 1373089Swyllys /* 1383089Swyllys * returns "len" on success and -1 on failure. 1393089Swyllys */ 1403089Swyllys ber_int_t 1413089Swyllys kmfber_write(BerElement *ber, char *buf, ber_len_t len, int nosos) 1423089Swyllys { 1433089Swyllys if (nosos || ber->ber_sos == NULL) { 1443089Swyllys if (ber->ber_ptr + len > ber->ber_end) { 1453089Swyllys if (kmfber_realloc(ber, len) != 0) 1463089Swyllys return (-1); 1473089Swyllys } 1483089Swyllys (void) memmove(ber->ber_ptr, buf, (size_t)len); 1493089Swyllys ber->ber_ptr += len; 1503089Swyllys return (len); 1513089Swyllys } else { 1523089Swyllys if (ber->ber_sos->sos_ptr + len > ber->ber_end) { 1533089Swyllys if (kmfber_realloc(ber, len) != 0) 1543089Swyllys return (-1); 1553089Swyllys } 1563089Swyllys (void) memmove(ber->ber_sos->sos_ptr, buf, (size_t)len); 1573089Swyllys ber->ber_sos->sos_ptr += len; 1583089Swyllys ber->ber_sos->sos_clen += len; 1593089Swyllys return (len); 1603089Swyllys } 1613089Swyllys } 1623089Swyllys 1633089Swyllys void 1643089Swyllys kmfber_free(BerElement *ber, int freebuf) 1653089Swyllys { 1663089Swyllys if (ber != NULL) { 167*10818Swyllys.ingersoll@sun.com if (freebuf && 168*10818Swyllys.ingersoll@sun.com !(ber->ber_flags & KMFBER_FLAG_NO_FREE_BUFFER)) 169*10818Swyllys.ingersoll@sun.com free(ber->ber_buf); 170*10818Swyllys.ingersoll@sun.com free((char *)ber); 1713089Swyllys } 1723089Swyllys } 1733089Swyllys 1743089Swyllys /* we pre-allocate a buffer to save the extra malloc later */ 1753089Swyllys BerElement * 1763089Swyllys kmfber_alloc_t(int options) 1773089Swyllys { 1783089Swyllys BerElement *ber; 1793089Swyllys 1803089Swyllys if ((ber = (BerElement*)calloc(1, 1813089Swyllys sizeof (struct berelement) + EXBUFSIZ)) == NULL) { 1823089Swyllys return (NULL); 1833089Swyllys } 1843089Swyllys 1853089Swyllys ber->ber_tag = KMFBER_DEFAULT; 1863089Swyllys ber->ber_options = options; 1873089Swyllys ber->ber_buf = (char *)ber + sizeof (struct berelement); 1883089Swyllys ber->ber_ptr = ber->ber_buf; 1893089Swyllys ber->ber_end = ber->ber_buf + EXBUFSIZ; 1903089Swyllys ber->ber_flags = KMFBER_FLAG_NO_FREE_BUFFER; 1913089Swyllys 1923089Swyllys return (ber); 1933089Swyllys } 1943089Swyllys 1953089Swyllys 1963089Swyllys BerElement * 1973089Swyllys kmfber_alloc() 1983089Swyllys { 1993089Swyllys return (kmfber_alloc_t(0)); 2003089Swyllys } 2013089Swyllys 2023089Swyllys BerElement * 2033089Swyllys kmfder_alloc() 2043089Swyllys { 2053089Swyllys return (kmfber_alloc_t(KMFBER_OPT_USE_DER)); 2063089Swyllys } 2073089Swyllys 2083089Swyllys BerElement * 2093089Swyllys kmfber_dup(BerElement *ber) 2103089Swyllys { 2113089Swyllys BerElement *new; 2123089Swyllys 2133089Swyllys if ((new = kmfber_alloc()) == NULL) 2143089Swyllys return (NULL); 2153089Swyllys 2163089Swyllys *new = *ber; 2173089Swyllys 2183089Swyllys return (new); 2193089Swyllys } 2203089Swyllys 2213089Swyllys 2223089Swyllys void 2233089Swyllys ber_init_w_nullchar(BerElement *ber, int options) 2243089Swyllys { 2253089Swyllys (void) memset((char *)ber, '\0', sizeof (struct berelement)); 2263089Swyllys ber->ber_tag = KMFBER_DEFAULT; 2273089Swyllys 2283089Swyllys ber->ber_options = options; 2293089Swyllys } 2303089Swyllys 2313089Swyllys 2323089Swyllys void 2333089Swyllys kmfber_reset(BerElement *ber, int was_writing) 2343089Swyllys { 2353089Swyllys if (was_writing) { 2363089Swyllys ber->ber_end = ber->ber_ptr; 2373089Swyllys ber->ber_ptr = ber->ber_buf; 2383089Swyllys } else { 2393089Swyllys ber->ber_ptr = ber->ber_end; 2403089Swyllys } 2413089Swyllys 2423089Swyllys ber->ber_rwptr = NULL; 2433089Swyllys } 2443089Swyllys 2453089Swyllys 2463089Swyllys #ifdef KMFBER_DEBUG 2473089Swyllys 2483089Swyllys void 2493089Swyllys ber_dump(BerElement *ber, int inout) 2503089Swyllys { 2513089Swyllys char msg[128]; 2523089Swyllys sprintf(msg, "ber_dump: buf 0x%lx, ptr 0x%lx, rwptr 0x%lx, end 0x%lx\n", 2533089Swyllys ber->ber_buf, ber->ber_ptr, ber->ber_rwptr, ber->ber_end); 2543089Swyllys ber_err_print(msg); 2553089Swyllys if (inout == 1) { 2563089Swyllys sprintf(msg, " current len %ld, contents:\n", 2573089Swyllys ber->ber_end - ber->ber_ptr); 2583089Swyllys ber_err_print(msg); 2593089Swyllys lber_bprint(ber->ber_ptr, ber->ber_end - ber->ber_ptr); 2603089Swyllys } else { 2613089Swyllys sprintf(msg, " current len %ld, contents:\n", 2623089Swyllys ber->ber_ptr - ber->ber_buf); 2633089Swyllys ber_err_print(msg); 2643089Swyllys lber_bprint(ber->ber_buf, ber->ber_ptr - ber->ber_buf); 2653089Swyllys } 2663089Swyllys } 2673089Swyllys 2683089Swyllys void 2693089Swyllys ber_sos_dump(Seqorset *sos) 2703089Swyllys { 2713089Swyllys char msg[80]; 2723089Swyllys ber_err_print("*** sos dump ***\n"); 2733089Swyllys while (sos != NULLSEQORSET) { 2743089Swyllys sprintf(msg, "ber_sos_dump: clen %ld first 0x%lx ptr 0x%lx\n", 2753089Swyllys sos->sos_clen, sos->sos_first, sos->sos_ptr); 2763089Swyllys ber_err_print(msg); 2773089Swyllys sprintf(msg, " current len %ld contents:\n", 2783089Swyllys sos->sos_ptr - sos->sos_first); 2793089Swyllys ber_err_print(msg); 2803089Swyllys lber_bprint(sos->sos_first, sos->sos_ptr - sos->sos_first); 2813089Swyllys 2823089Swyllys sos = sos->sos_next; 2833089Swyllys } 2843089Swyllys ber_err_print("*** end dump ***\n"); 2853089Swyllys } 2863089Swyllys 2873089Swyllys #endif 2883089Swyllys 2893089Swyllys /* new dboreham code below: */ 2903089Swyllys struct byte_buffer { 2913089Swyllys unsigned char *p; 2923089Swyllys int offset; 2933089Swyllys int length; 2943089Swyllys }; 2953089Swyllys typedef struct byte_buffer byte_buffer; 2963089Swyllys 2973089Swyllys /* 2983089Swyllys * The kmfber_flatten routine allocates a struct berval whose contents 2993089Swyllys * are a BER encoding taken from the ber argument. The bvPtr pointer 3003089Swyllys * points to the returned berval, which must be freed using 3013089Swyllys * kmfber_bvfree(). This routine returns 0 on success and -1 on error. 3023089Swyllys * The use of kmfber_flatten on a BerElement in which all '{' and '}' 3033089Swyllys * format modifiers have not been properly matched can result in a 3043089Swyllys * berval whose contents are not a valid BER encoding. 3053089Swyllys * Note that the ber_ptr is not modified. 3063089Swyllys */ 3073089Swyllys int 3083089Swyllys kmfber_flatten(BerElement *ber, struct berval **bvPtr) 3093089Swyllys { 3103089Swyllys struct berval *new; 3113089Swyllys ber_len_t len; 3123089Swyllys 3133089Swyllys /* allocate a struct berval */ 3143089Swyllys new = (struct berval *)malloc((size_t)(sizeof (struct berval))); 3153089Swyllys if (new == NULL) { 3163089Swyllys return (-1); 3173089Swyllys } 3183089Swyllys (void) memset(new, 0, sizeof (struct berval)); 3193089Swyllys 3203089Swyllys /* 3213089Swyllys * Copy everything from the BerElement's ber_buf to ber_ptr 3223089Swyllys * into the berval structure. 3233089Swyllys */ 3243089Swyllys if (ber == NULL) { 3253089Swyllys new->bv_val = NULL; 3263089Swyllys new->bv_len = 0; 3273089Swyllys } else { 3283089Swyllys len = ber->ber_ptr - ber->ber_buf; 3293089Swyllys new->bv_val = (char *)malloc((size_t)(len + 1)); 3303089Swyllys if (new->bv_val == NULL) { 3313089Swyllys kmfber_bvfree(new); 3323089Swyllys return (-1); 3333089Swyllys } 3343089Swyllys (void) memmove(new->bv_val, ber->ber_buf, (size_t)len); 3353089Swyllys new->bv_val[len] = '\0'; 3363089Swyllys new->bv_len = len; 3373089Swyllys } 3383089Swyllys 3393089Swyllys /* set bvPtr pointer to point to the returned berval */ 3403089Swyllys *bvPtr = new; 3413089Swyllys 3423089Swyllys return (0); 3433089Swyllys } 3443089Swyllys 3453089Swyllys BerElement * 3463089Swyllys kmfder_init(const struct berval *bv) 3473089Swyllys { 3483089Swyllys BerElement *ber; 3493089Swyllys 3503089Swyllys /* construct BerElement */ 3513089Swyllys if ((ber = kmfber_alloc_t(KMFBER_OPT_USE_DER)) != NULL) { 3523089Swyllys /* copy data from the bv argument into BerElement */ 3533089Swyllys /* XXXmcs: had to cast unsigned long bv_len to long */ 3543089Swyllys if ((kmfber_write(ber, bv->bv_val, bv->bv_len, 0)) != 355*10818Swyllys.ingersoll@sun.com (ber_slen_t)bv->bv_len) { 3563089Swyllys kmfber_free(ber, 1); 3573089Swyllys return (NULL); 3583089Swyllys } 3593089Swyllys } 3603089Swyllys /* 3613089Swyllys * reset ber_ptr back to the beginning of buffer so that this new 3623089Swyllys * and initialized ber element can be READ 3633089Swyllys */ 3643089Swyllys kmfber_reset(ber, 1); 3653089Swyllys 3663089Swyllys /* 3673089Swyllys * return a ptr to a new BerElement containing a copy of the data 3683089Swyllys * in the bv argument or a null pointer on error 3693089Swyllys */ 3703089Swyllys return (ber); 3713089Swyllys } 3723089Swyllys 3733089Swyllys BerElement * 3743089Swyllys kmfber_init(const struct berval *bv) 3753089Swyllys { 3763089Swyllys BerElement *ber; 3773089Swyllys 3783089Swyllys /* construct BerElement */ 3793089Swyllys if ((ber = kmfber_alloc_t(0)) != NULL) { 3803089Swyllys /* copy data from the bv argument into BerElement */ 3813089Swyllys /* XXXmcs: had to cast unsigned long bv_len to long */ 3823089Swyllys if ((kmfber_write(ber, bv->bv_val, bv->bv_len, 0)) != 383*10818Swyllys.ingersoll@sun.com (ber_slen_t)bv->bv_len) { 3843089Swyllys kmfber_free(ber, 1); 3853089Swyllys return (NULL); 3863089Swyllys } 3873089Swyllys } 3883089Swyllys /* 3893089Swyllys * reset ber_ptr back to the beginning of buffer so that this new 3903089Swyllys * and initialized ber element can be READ 3913089Swyllys */ 3923089Swyllys kmfber_reset(ber, 1); 3933089Swyllys 3943089Swyllys /* 3953089Swyllys * return a ptr to a new BerElement containing a copy of the data 3963089Swyllys * in the bv argument or a null pointer on error 3973089Swyllys */ 3983089Swyllys return (ber); 3993089Swyllys } 400