/* For encode.c and decode.c in HEAD/libraries/liblber/ */ int ber_encode_oid( BerValue *in, BerValue *out ) { unsigned char *der; unsigned long val; unsigned val1; int i, j, len; char *ptr, *end, *inend; assert( in != NULL ); assert( out != NULL ); /* This size check could be defeated with negative input (which glibc * accepts even for %u), so we use LONG_MAX as max limit/error mark. */ if ( !out->bv_val || out->bv_len < in->bv_len ) return -1; /* OIDs must have at least two components: <0-1>.<0-39> or 2. */ if ( sscanf( in->bv_val, "%u.%lu%n", &val1, &val, &len ) != 2 ) return -1; if ( val1 < 2 ? val > 39 : (val1 > 2 || val >= LONG_MAX) ) return -1; val += val1 * 40; ptr = in->bv_val + len; inend = in->bv_val + in->bv_len; der = (unsigned char *) out->bv_val; for (;;) { len = 0; do { der[len++] = (val & 0x7f) | 0x80; } while ( (val >>= 7) != 0 ); der[0] &= 0x7f; for ( i = 0, j = len; i < --j; i++ ) { unsigned char tmp = der[i]; der[i] = der[j]; der[j] = tmp; } der += len; if ( ptr >= inend ) break; if ( *ptr++ != '.' ) return -1; val = strtol( ptr, &end, 10 ); if ( ptr == end || val >= LONG_MAX ) return -1; ptr = end; } out->bv_len = (char *)der - out->bv_val; return 0; } int ber_decode_oid( BerValue *in, BerValue *out ) { unsigned char *der; unsigned long val; unsigned val1; ber_len_t i; char *ptr; assert( in != NULL ); assert( out != NULL ); /* 4 chars per inbyte + \0 (needed for input {7f 7f 7f...}) */ if ( !out->bv_val || out->bv_len <= in->bv_len * 4 ) return -1; ptr = NULL; val = 0; der = (unsigned char *) in->bv_val; for ( i=0; i < in->bv_len; i++ ) { if ( val >= (LONG_MAX >> 7) ) /* matches encode.c LONG_MAX limit */ return -1; val = val << 7; val |= der[i] & 0x7f; if ( !( der[i] & 0x80 )) { if ( ptr == NULL ) { ptr = out->bv_val; val1 = (val < 80 ? val/40 : 2); val -= 40*val1; ptr += sprintf( ptr, "%u", val1 ); } ptr += sprintf( ptr, ".%lu", val ); val = 0; } else if ( val == 0 ) { return -1; /* subidentifier may not start with 0x80 */ } } if ( ptr == NULL || val != 0 ) return -1; out->bv_len = ptr - out->bv_val; return 0; }