17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate * Use is subject to license terms. 47c478bd9Sstevel@tonic-gate */ 57c478bd9Sstevel@tonic-gate 67c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 77c478bd9Sstevel@tonic-gate 87c478bd9Sstevel@tonic-gate /* Coding Buffer Implementation */ 97c478bd9Sstevel@tonic-gate 107c478bd9Sstevel@tonic-gate /* 117c478bd9Sstevel@tonic-gate Implementation 127c478bd9Sstevel@tonic-gate 137c478bd9Sstevel@tonic-gate Encoding mode 147c478bd9Sstevel@tonic-gate 157c478bd9Sstevel@tonic-gate The encoding buffer is filled from bottom (lowest address) to top 167c478bd9Sstevel@tonic-gate (highest address). This makes it easier to expand the buffer, 177c478bd9Sstevel@tonic-gate since realloc preserves the existing portion of the buffer. 187c478bd9Sstevel@tonic-gate 197c478bd9Sstevel@tonic-gate Note: Since ASN.1 encoding must be done in reverse, this means 207c478bd9Sstevel@tonic-gate that you can't simply memcpy out the buffer data, since it will be 217c478bd9Sstevel@tonic-gate backwards. You need to reverse-iterate through it, instead. 227c478bd9Sstevel@tonic-gate 237c478bd9Sstevel@tonic-gate ***This decision may have been a mistake. In practice, the 247c478bd9Sstevel@tonic-gate implementation will probably be tuned such that reallocation is 257c478bd9Sstevel@tonic-gate rarely necessary. Also, the realloc probably has recopy the 267c478bd9Sstevel@tonic-gate buffer itself, so we don't really gain that much by avoiding an 277c478bd9Sstevel@tonic-gate explicit copy of the buffer. --Keep this in mind for future reference. 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate Decoding mode 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate The decoding buffer is in normal order and is created by wrapping 337c478bd9Sstevel@tonic-gate an asn1buf around a krb5_data structure. 347c478bd9Sstevel@tonic-gate */ 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate /* Abstraction Function 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate Programs should use just pointers to asn1buf's (e.g. asn1buf *mybuf). 397c478bd9Sstevel@tonic-gate These pointers must always point to a valid, allocated asn1buf 407c478bd9Sstevel@tonic-gate structure or be NULL. 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate The contents of the asn1buf represent an octet string. This string 437c478bd9Sstevel@tonic-gate begins at base and continues to the octet immediately preceding next. 447c478bd9Sstevel@tonic-gate If next == base or mybuf == NULL, then the asn1buf represents an empty 457c478bd9Sstevel@tonic-gate octet string. */ 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate /* Representation Invariant 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate Pointers to asn1buf's must always point to a valid, allocated 507c478bd9Sstevel@tonic-gate asn1buf structure or be NULL. 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate base points to a valid, allocated octet array or is NULL 537c478bd9Sstevel@tonic-gate bound, if non-NULL, points to the last valid octet 547c478bd9Sstevel@tonic-gate next >= base 55*505d05c7Sgtb next <= bound+2 (i.e. next should be able to step just past the bound, 567c478bd9Sstevel@tonic-gate but no further. (The bound should move out in response 577c478bd9Sstevel@tonic-gate to being crossed by next.)) */ 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate #define ASN1BUF_OMIT_INLINE_FUNCS 607c478bd9Sstevel@tonic-gate #include "asn1buf.h" 617c478bd9Sstevel@tonic-gate #undef ASN1BUF_OMIT_INLINE_FUNCS 627c478bd9Sstevel@tonic-gate #include <stdio.h> 637c478bd9Sstevel@tonic-gate #include "asn1_get.h" 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate #define asn1_is_eoc(class, num, indef) \ 667c478bd9Sstevel@tonic-gate ((class) == UNIVERSAL && !(num) && !(indef)) 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate asn1_error_code asn1buf_create(asn1buf **buf) 697c478bd9Sstevel@tonic-gate { 707c478bd9Sstevel@tonic-gate *buf = (asn1buf*)malloc(sizeof(asn1buf)); 717c478bd9Sstevel@tonic-gate if (*buf == NULL) return ENOMEM; 727c478bd9Sstevel@tonic-gate (*buf)->base = NULL; 737c478bd9Sstevel@tonic-gate (*buf)->bound = NULL; 747c478bd9Sstevel@tonic-gate (*buf)->next = NULL; 757c478bd9Sstevel@tonic-gate return 0; 767c478bd9Sstevel@tonic-gate } 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate asn1_error_code asn1buf_wrap_data(asn1buf *buf, const krb5_data *code) 797c478bd9Sstevel@tonic-gate { 807c478bd9Sstevel@tonic-gate if(code == NULL || code->data == NULL) return ASN1_MISSING_FIELD; 817c478bd9Sstevel@tonic-gate buf->next = buf->base = code->data; 827c478bd9Sstevel@tonic-gate buf->bound = code->data + code->length - 1; 837c478bd9Sstevel@tonic-gate return 0; 847c478bd9Sstevel@tonic-gate } 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate asn1_error_code asn1buf_imbed(asn1buf *subbuf, const asn1buf *buf, const unsigned int length, const int indef) 877c478bd9Sstevel@tonic-gate { 887c478bd9Sstevel@tonic-gate subbuf->base = subbuf->next = buf->next; 897c478bd9Sstevel@tonic-gate if (!indef) { 907c478bd9Sstevel@tonic-gate subbuf->bound = subbuf->base + length - 1; 917c478bd9Sstevel@tonic-gate if (subbuf->bound > buf->bound) 927c478bd9Sstevel@tonic-gate return ASN1_OVERRUN; 937c478bd9Sstevel@tonic-gate } else /* constructed indefinite */ 947c478bd9Sstevel@tonic-gate subbuf->bound = buf->bound; 957c478bd9Sstevel@tonic-gate return 0; 967c478bd9Sstevel@tonic-gate } 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate asn1_error_code asn1buf_sync(asn1buf *buf, asn1buf *subbuf, 997c478bd9Sstevel@tonic-gate asn1_class asn1class, asn1_tagnum lasttag, 1007c478bd9Sstevel@tonic-gate unsigned int length, int indef, int seqindef) 1017c478bd9Sstevel@tonic-gate { 1027c478bd9Sstevel@tonic-gate asn1_error_code retval; 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate if (!seqindef) { 1057c478bd9Sstevel@tonic-gate /* sequence was encoded as definite length */ 1067c478bd9Sstevel@tonic-gate buf->next = subbuf->bound + 1; 1077c478bd9Sstevel@tonic-gate } else if (!asn1_is_eoc(asn1class, lasttag, indef)) { 1087c478bd9Sstevel@tonic-gate retval = asn1buf_skiptail(subbuf, length, indef); 1097c478bd9Sstevel@tonic-gate if (retval) 1107c478bd9Sstevel@tonic-gate return retval; 1117c478bd9Sstevel@tonic-gate } else { 1127c478bd9Sstevel@tonic-gate /* We have just read the EOC octets. */ 1137c478bd9Sstevel@tonic-gate buf->next = subbuf->next; 1147c478bd9Sstevel@tonic-gate } 1157c478bd9Sstevel@tonic-gate return 0; 1167c478bd9Sstevel@tonic-gate } 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate asn1_error_code asn1buf_skiptail(asn1buf *buf, const unsigned int length, const int indef) 1197c478bd9Sstevel@tonic-gate { 1207c478bd9Sstevel@tonic-gate asn1_error_code retval; 1217c478bd9Sstevel@tonic-gate taginfo t; 1227c478bd9Sstevel@tonic-gate int nestlevel; 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate nestlevel = 1 + indef; 1257c478bd9Sstevel@tonic-gate if (!indef) { 1267c478bd9Sstevel@tonic-gate if (length <= buf->bound - buf->next + 1) 1277c478bd9Sstevel@tonic-gate buf->next += length; 1287c478bd9Sstevel@tonic-gate else 1297c478bd9Sstevel@tonic-gate return ASN1_OVERRUN; 1307c478bd9Sstevel@tonic-gate } 1317c478bd9Sstevel@tonic-gate while (nestlevel > 0) { 132*505d05c7Sgtb if (buf->bound - buf->next + 1 <= 0) 133*505d05c7Sgtb return ASN1_OVERRUN; 1347c478bd9Sstevel@tonic-gate retval = asn1_get_tag_2(buf, &t); 1357c478bd9Sstevel@tonic-gate if (retval) return retval; 1367c478bd9Sstevel@tonic-gate if (!t.indef) { 1377c478bd9Sstevel@tonic-gate if (t.length <= buf->bound - buf->next + 1) 1387c478bd9Sstevel@tonic-gate buf->next += t.length; 1397c478bd9Sstevel@tonic-gate else 1407c478bd9Sstevel@tonic-gate return ASN1_OVERRUN; 1417c478bd9Sstevel@tonic-gate } 1427c478bd9Sstevel@tonic-gate if (t.indef) 1437c478bd9Sstevel@tonic-gate nestlevel++; 1447c478bd9Sstevel@tonic-gate if (asn1_is_eoc(t.asn1class, t.tagnum, t.indef)) 1457c478bd9Sstevel@tonic-gate nestlevel--; /* got an EOC encoding */ 1467c478bd9Sstevel@tonic-gate } 1477c478bd9Sstevel@tonic-gate return 0; 1487c478bd9Sstevel@tonic-gate } 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate asn1_error_code asn1buf_destroy(asn1buf **buf) 1517c478bd9Sstevel@tonic-gate { 1527c478bd9Sstevel@tonic-gate if (*buf != NULL) { 1537c478bd9Sstevel@tonic-gate if ((*buf)->base != NULL) free((*buf)->base); 1547c478bd9Sstevel@tonic-gate free(*buf); 1557c478bd9Sstevel@tonic-gate *buf = NULL; 1567c478bd9Sstevel@tonic-gate } 1577c478bd9Sstevel@tonic-gate return 0; 1587c478bd9Sstevel@tonic-gate } 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate #ifdef asn1buf_insert_octet 1617c478bd9Sstevel@tonic-gate #undef asn1buf_insert_octet 1627c478bd9Sstevel@tonic-gate #endif 1637c478bd9Sstevel@tonic-gate asn1_error_code asn1buf_insert_octet(asn1buf *buf, const int o) 1647c478bd9Sstevel@tonic-gate { 1657c478bd9Sstevel@tonic-gate asn1_error_code retval; 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate retval = asn1buf_ensure_space(buf,1U); 1687c478bd9Sstevel@tonic-gate if(retval) return retval; 1697c478bd9Sstevel@tonic-gate *(buf->next) = (char)o; 1707c478bd9Sstevel@tonic-gate (buf->next)++; 1717c478bd9Sstevel@tonic-gate return 0; 1727c478bd9Sstevel@tonic-gate } 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate asn1_error_code asn1buf_insert_octetstring(asn1buf *buf, const unsigned int len, const krb5_octet *s) 1757c478bd9Sstevel@tonic-gate { 1767c478bd9Sstevel@tonic-gate asn1_error_code retval; 1777c478bd9Sstevel@tonic-gate int length; 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate retval = asn1buf_ensure_space(buf,len); 1807c478bd9Sstevel@tonic-gate if(retval) return retval; 1817c478bd9Sstevel@tonic-gate for(length=1; length<=len; length++,(buf->next)++) 1827c478bd9Sstevel@tonic-gate *(buf->next) = (char)(s[len-length]); 1837c478bd9Sstevel@tonic-gate return 0; 1847c478bd9Sstevel@tonic-gate } 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate asn1_error_code asn1buf_insert_charstring(asn1buf *buf, const unsigned int len, const char *s) 1877c478bd9Sstevel@tonic-gate { 1887c478bd9Sstevel@tonic-gate asn1_error_code retval; 1897c478bd9Sstevel@tonic-gate int length; 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate retval = asn1buf_ensure_space(buf,len); 1927c478bd9Sstevel@tonic-gate if(retval) return retval; 1937c478bd9Sstevel@tonic-gate for(length=1; length<=len; length++,(buf->next)++) 1947c478bd9Sstevel@tonic-gate *(buf->next) = (char)(s[len-length]); 1957c478bd9Sstevel@tonic-gate return 0; 1967c478bd9Sstevel@tonic-gate } 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate #undef asn1buf_remove_octet 1997c478bd9Sstevel@tonic-gate asn1_error_code asn1buf_remove_octet(asn1buf *buf, asn1_octet *o) 2007c478bd9Sstevel@tonic-gate { 2017c478bd9Sstevel@tonic-gate if(buf->next > buf->bound) return ASN1_OVERRUN; 2027c478bd9Sstevel@tonic-gate *o = (asn1_octet)(*((buf->next)++)); 2037c478bd9Sstevel@tonic-gate return 0; 2047c478bd9Sstevel@tonic-gate } 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate asn1_error_code asn1buf_remove_octetstring(asn1buf *buf, const unsigned int len, asn1_octet **s) 2077c478bd9Sstevel@tonic-gate { 2087c478bd9Sstevel@tonic-gate int i; 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate if (len > buf->bound + 1 - buf->next) return ASN1_OVERRUN; 2117c478bd9Sstevel@tonic-gate if (len == 0) { 2127c478bd9Sstevel@tonic-gate *s = 0; 2137c478bd9Sstevel@tonic-gate return 0; 2147c478bd9Sstevel@tonic-gate } 2157c478bd9Sstevel@tonic-gate *s = (asn1_octet*)malloc(len*sizeof(asn1_octet)); 2167c478bd9Sstevel@tonic-gate if (*s == NULL) 2177c478bd9Sstevel@tonic-gate return ENOMEM; 2187c478bd9Sstevel@tonic-gate for(i=0; i<len; i++) 2197c478bd9Sstevel@tonic-gate (*s)[i] = (asn1_octet)(buf->next)[i]; 2207c478bd9Sstevel@tonic-gate buf->next += len; 2217c478bd9Sstevel@tonic-gate return 0; 2227c478bd9Sstevel@tonic-gate } 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate asn1_error_code asn1buf_remove_charstring(asn1buf *buf, const unsigned int len, char **s) 2257c478bd9Sstevel@tonic-gate { 2267c478bd9Sstevel@tonic-gate int i; 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate if (len > buf->bound + 1 - buf->next) return ASN1_OVERRUN; 2297c478bd9Sstevel@tonic-gate if (len == 0) { 2307c478bd9Sstevel@tonic-gate *s = 0; 2317c478bd9Sstevel@tonic-gate return 0; 2327c478bd9Sstevel@tonic-gate } 2337c478bd9Sstevel@tonic-gate *s = (char*)malloc(len*sizeof(char)); 2347c478bd9Sstevel@tonic-gate if (*s == NULL) return ENOMEM; 2357c478bd9Sstevel@tonic-gate for(i=0; i<len; i++) 2367c478bd9Sstevel@tonic-gate (*s)[i] = (char)(buf->next)[i]; 2377c478bd9Sstevel@tonic-gate buf->next += len; 2387c478bd9Sstevel@tonic-gate return 0; 2397c478bd9Sstevel@tonic-gate } 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate int asn1buf_remains(asn1buf *buf, int indef) 2427c478bd9Sstevel@tonic-gate { 2437c478bd9Sstevel@tonic-gate int remain; 2447c478bd9Sstevel@tonic-gate if(buf == NULL || buf->base == NULL) return 0; 2457c478bd9Sstevel@tonic-gate remain = buf->bound - buf->next +1; 2467c478bd9Sstevel@tonic-gate if (remain <= 0) return remain; 2477c478bd9Sstevel@tonic-gate /* 2487c478bd9Sstevel@tonic-gate * Two 0 octets means the end of an indefinite encoding. 2497c478bd9Sstevel@tonic-gate */ 2507c478bd9Sstevel@tonic-gate if (indef && remain >= 2 && !*(buf->next) && !*(buf->next + 1)) 2517c478bd9Sstevel@tonic-gate return 0; 2527c478bd9Sstevel@tonic-gate else return remain; 2537c478bd9Sstevel@tonic-gate } 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate asn1_error_code asn12krb5_buf(const asn1buf *buf, krb5_data **code) 2567c478bd9Sstevel@tonic-gate { 2577c478bd9Sstevel@tonic-gate int i; 2587c478bd9Sstevel@tonic-gate *code = (krb5_data*)calloc(1,sizeof(krb5_data)); 2597c478bd9Sstevel@tonic-gate if(*code == NULL) return ENOMEM; 2607c478bd9Sstevel@tonic-gate (*code)->magic = KV5M_DATA; 2617c478bd9Sstevel@tonic-gate (*code)->data = NULL; 2627c478bd9Sstevel@tonic-gate (*code)->length = 0; 2637c478bd9Sstevel@tonic-gate (*code)->length = asn1buf_len(buf); 2647c478bd9Sstevel@tonic-gate (*code)->data = (char*)malloc((((*code)->length)+1)*sizeof(char)); 2657c478bd9Sstevel@tonic-gate if ((*code)->data == NULL) { 2667c478bd9Sstevel@tonic-gate free(*code); 2677c478bd9Sstevel@tonic-gate *code = NULL; 2687c478bd9Sstevel@tonic-gate return ENOMEM; 2697c478bd9Sstevel@tonic-gate } 2707c478bd9Sstevel@tonic-gate for(i=0; i < (*code)->length; i++) 2717c478bd9Sstevel@tonic-gate ((*code)->data)[i] = (buf->base)[((*code)->length)-i-1]; 2727c478bd9Sstevel@tonic-gate ((*code)->data)[(*code)->length] = '\0'; 2737c478bd9Sstevel@tonic-gate return 0; 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate 2787c478bd9Sstevel@tonic-gate /* These parse and unparse procedures should be moved out. They're 2797c478bd9Sstevel@tonic-gate useful only for debugging and superfluous in the production version. */ 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate asn1_error_code asn1buf_unparse(const asn1buf *buf, char **s) 2827c478bd9Sstevel@tonic-gate { 2837c478bd9Sstevel@tonic-gate if(*s != NULL) free(*s); 2847c478bd9Sstevel@tonic-gate if(buf == NULL){ 2857c478bd9Sstevel@tonic-gate *s = malloc(sizeof("<NULL>")); 2867c478bd9Sstevel@tonic-gate if(*s == NULL) return ENOMEM; 2877c478bd9Sstevel@tonic-gate strcpy(*s,"<NULL>"); 2887c478bd9Sstevel@tonic-gate }else if(buf->base == NULL){ 2897c478bd9Sstevel@tonic-gate *s = malloc(sizeof("<EMPTY>")); 2907c478bd9Sstevel@tonic-gate if(*s == NULL) return ENOMEM; 2917c478bd9Sstevel@tonic-gate strcpy(*s,"<EMPTY>"); 2927c478bd9Sstevel@tonic-gate }else{ 2937c478bd9Sstevel@tonic-gate unsigned int length = asn1buf_len(buf); 2947c478bd9Sstevel@tonic-gate int i; 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate *s = calloc(length+1, sizeof(char)); 2977c478bd9Sstevel@tonic-gate if(*s == NULL) return ENOMEM; 2987c478bd9Sstevel@tonic-gate (*s)[length] = '\0'; 2997c478bd9Sstevel@tonic-gate for(i=0; i<length; i++) ; 3007c478bd9Sstevel@tonic-gate /* OLDDECLARG( (*s)[i] = , (buf->base)[length-i-1]) */ 3017c478bd9Sstevel@tonic-gate } 3027c478bd9Sstevel@tonic-gate return 0; 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate asn1_error_code asn1buf_hex_unparse(const asn1buf *buf, char **s) 3067c478bd9Sstevel@tonic-gate { 3077c478bd9Sstevel@tonic-gate #define hexchar(d) ((d)<=9 ? ('0'+(d)) :\ 3087c478bd9Sstevel@tonic-gate ((d)<=15 ? ('A'+(d)-10) :\ 3097c478bd9Sstevel@tonic-gate 'X')) 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate if(*s != NULL) free(*s); 3127c478bd9Sstevel@tonic-gate 3137c478bd9Sstevel@tonic-gate if(buf == NULL){ 3147c478bd9Sstevel@tonic-gate *s = malloc(sizeof("<NULL>")); 3157c478bd9Sstevel@tonic-gate if(*s == NULL) return ENOMEM; 3167c478bd9Sstevel@tonic-gate strcpy(*s,"<NULL>"); 3177c478bd9Sstevel@tonic-gate }else if(buf->base == NULL){ 3187c478bd9Sstevel@tonic-gate *s = malloc(sizeof("<EMPTY>")); 3197c478bd9Sstevel@tonic-gate if(*s == NULL) return ENOMEM; 3207c478bd9Sstevel@tonic-gate strcpy(*s,"<EMPTY>"); 3217c478bd9Sstevel@tonic-gate }else{ 3227c478bd9Sstevel@tonic-gate unsigned int length = asn1buf_len(buf); 3237c478bd9Sstevel@tonic-gate int i; 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate *s = malloc(3*length); 3267c478bd9Sstevel@tonic-gate if(*s == NULL) return ENOMEM; 3277c478bd9Sstevel@tonic-gate for(i = length-1; i >= 0; i--){ 3287c478bd9Sstevel@tonic-gate (*s)[3*(length-i-1)] = hexchar(((buf->base)[i]&0xF0)>>4); 3297c478bd9Sstevel@tonic-gate (*s)[3*(length-i-1)+1] = hexchar((buf->base)[i]&0x0F); 3307c478bd9Sstevel@tonic-gate (*s)[3*(length-i-1)+2] = ' '; 3317c478bd9Sstevel@tonic-gate } 3327c478bd9Sstevel@tonic-gate (*s)[3*length-1] = '\0'; 3337c478bd9Sstevel@tonic-gate } 3347c478bd9Sstevel@tonic-gate return 0; 3357c478bd9Sstevel@tonic-gate } 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate /****************************************************************/ 3387c478bd9Sstevel@tonic-gate /* Private Procedures */ 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate #undef asn1buf_size 3417c478bd9Sstevel@tonic-gate int asn1buf_size(const asn1buf *buf) 3427c478bd9Sstevel@tonic-gate { 3437c478bd9Sstevel@tonic-gate if(buf == NULL || buf->base == NULL) return 0; 3447c478bd9Sstevel@tonic-gate return buf->bound - buf->base + 1; 3457c478bd9Sstevel@tonic-gate } 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate #undef asn1buf_free 3487c478bd9Sstevel@tonic-gate int asn1buf_free(const asn1buf *buf) 3497c478bd9Sstevel@tonic-gate { 3507c478bd9Sstevel@tonic-gate if(buf == NULL || buf->base == NULL) return 0; 3517c478bd9Sstevel@tonic-gate else return buf->bound - buf->next + 1; 3527c478bd9Sstevel@tonic-gate } 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate #undef asn1buf_ensure_space 3557c478bd9Sstevel@tonic-gate asn1_error_code asn1buf_ensure_space(asn1buf *buf, const unsigned int amount) 3567c478bd9Sstevel@tonic-gate { 3577c478bd9Sstevel@tonic-gate int avail = asn1buf_free(buf); 3587c478bd9Sstevel@tonic-gate if(avail < amount){ 3597c478bd9Sstevel@tonic-gate asn1_error_code retval = asn1buf_expand(buf, amount-avail); 3607c478bd9Sstevel@tonic-gate if(retval) return retval; 3617c478bd9Sstevel@tonic-gate } 3627c478bd9Sstevel@tonic-gate return 0; 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate asn1_error_code asn1buf_expand(asn1buf *buf, unsigned int inc) 3667c478bd9Sstevel@tonic-gate { 3677c478bd9Sstevel@tonic-gate #define STANDARD_INCREMENT 200 3687c478bd9Sstevel@tonic-gate int next_offset = buf->next - buf->base; 3697c478bd9Sstevel@tonic-gate int bound_offset; 3707c478bd9Sstevel@tonic-gate if (buf->base == NULL) bound_offset = -1; 3717c478bd9Sstevel@tonic-gate else bound_offset = buf->bound - buf->base; 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate if (inc < STANDARD_INCREMENT) 3747c478bd9Sstevel@tonic-gate inc = STANDARD_INCREMENT; 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate if (buf->base == NULL) 3777c478bd9Sstevel@tonic-gate buf->base = malloc((asn1buf_size(buf)+inc) * sizeof(asn1_octet)); 3787c478bd9Sstevel@tonic-gate else 3797c478bd9Sstevel@tonic-gate buf->base = realloc(buf->base, 3807c478bd9Sstevel@tonic-gate (asn1buf_size(buf)+inc) * sizeof(asn1_octet)); 3817c478bd9Sstevel@tonic-gate if (buf->base == NULL) return ENOMEM; 3827c478bd9Sstevel@tonic-gate buf->bound = (buf->base) + bound_offset + inc; 3837c478bd9Sstevel@tonic-gate buf->next = (buf->base) + next_offset; 3847c478bd9Sstevel@tonic-gate return 0; 3857c478bd9Sstevel@tonic-gate } 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate #undef asn1buf_len 3887c478bd9Sstevel@tonic-gate int asn1buf_len(const asn1buf *buf) 3897c478bd9Sstevel@tonic-gate { 3907c478bd9Sstevel@tonic-gate return buf->next - buf->base; 3917c478bd9Sstevel@tonic-gate } 392