encode.c revision 56664548661c43ae04de4a32bce3510ed36aeaf9
/*
* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
* Copyright (c) 1990 Regents of the University of Michigan.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and that due credit is given
* to the University of Michigan at Ann Arbor. The name of the University
* may not be used to endorse or promote products derived from this
* software without specific prior written permission. This software
* is provided ``as is'' without express or implied warranty.
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <inttypes.h>
#include <ber_der.h>
#include "kmfber_int.h"
/* the following constants are used in kmfber_calc_lenlen */
#define LENMASK1 0xFF
#define LENMASK2 0xFFFF
#define LENMASK3 0xFFFFFF
#define LENMASK4 0xFFFFFFFF
#define _MASK 0x80
int
{
int i;
/* find the first non-all-zero byte in the tag */
for (i = sizeof (ber_int_t) - 1; i > 0; i--) {
/* not all zero */
break;
}
return (i + 1);
}
static int
{
return (kmfber_write(ber,
}
int
{
/*
* short len if it's less than 128 - one byte giving the len,
* with bit 8 0.
*/
if (len <= 0x7F)
return (1);
/*
* long len otherwise - one byte with bit 8 set, giving the
* length of the length, followed by the length itself.
*/
return (2);
return (3);
return (4);
return (5);
}
int
{
int i;
char lenlen;
/*
* short len if it's less than 128 - one byte giving the len,
* with bit 8 0.
*/
if (len <= 127) {
return (kmfber_write(ber,
1, nosos));
}
/*
* long len otherwise - one byte with bit 8 set, giving the
* length of the length, followed by the length itself.
*/
/* find the first non-all-zero byte */
for (i = sizeof (ber_int_t) - 1; i > 0; i--) {
/* not all zero */
break;
}
lenlen = ++i;
if (lenlen > 4)
return (-1);
lenlen |= 0x80;
/* write the length of the length */
return (-1);
/* write the length itself */
if (kmfber_write(ber,
return (-1);
return (i + 1);
}
static int
{
int i, sign;
/*
* high bit is set - look for first non-all-one byte
* high bit is clear - look for first non-all-zero byte
*/
for (i = sizeof (ber_int_t) - 1; i > 0; i--) {
if (sign) {
/* not all ones */
break;
} else {
/* not all zero */
break;
}
}
/*
* we now have the "leading byte". if the high bit on this
* byte matches the sign bit, we need to "back up" a byte.
*/
i++;
len = i + 1;
return (-1);
return (-1);
i++;
if (kmfber_write(ber,
/* length of tag + length + contents */
return (-1);
}
static int
{
if (tag == KMFBER_DEFAULT)
}
int
{
if (tag == KMFBER_DEFAULT)
tag = BER_INTEGER;
}
int
{
if (tag == KMFBER_DEFAULT)
return (-1);
rc = -1;
} else {
/* return length of tag + length + contents */
}
return (rc);
}
int
{
char zero = 0x00;
if (tag == KMFBER_DEFAULT)
tag = BER_INTEGER;
return (-1);
/* Add a leading 0 if the high order bit is set */
if (data[0] & 0x80)
len++;
return (-1);
/* add leading 0 if hi bit set */
return (-1);
/* Adjust the length of the write if hi-order bit is set */
if (data[0] & 0x80)
return (-1);
} else {
/* return length of tag + length + contents */
}
return (rc);
}
static int
{
#ifdef STR_TRANSLATION
int free_str;
#endif /* STR_TRANSLATION */
if (tag == KMFBER_DEFAULT)
return (-1);
#ifdef STR_TRANSLATION
!= 0) {
return (-1);
}
free_str = 1;
} else {
free_str = 0;
}
#endif /* STR_TRANSLATION */
/*
* Note: below is a spot where we limit ber_write
* to signed long (instead of unsigned long)
*/
rc = -1;
} else {
/* return length of tag + length + contents */
}
#ifdef STR_TRANSLATION
if (free_str) {
}
#endif /* STR_TRANSLATION */
return (rc);
}
static int
{
}
static int
{
unsigned char unusedbits;
if (tag == KMFBER_DEFAULT)
return (-1);
return (-1);
return (-1);
return (-1);
/* return length of tag + length + unused bit count + contents */
}
static int
{
int taglen;
if (tag == KMFBER_DEFAULT)
return (-1);
return (-1);
return (taglen + 1);
}
static int
{
int taglen;
unsigned char trueval = 0xff;
unsigned char falseval = 0x00;
if (tag == KMFBER_DEFAULT)
tag = BER_BOOLEAN;
return (-1);
return (-1);
!= 1)
return (-1);
return (taglen + 2);
}
#define FOUR_BYTE_LEN 5
/*
* The idea here is roughly this: we maintain a stack of these Seqorset
* structures. This is pushed when we see the beginning of a new set or
* sequence. It is popped when we see the end of a set or sequence.
* Since we don't want to malloc and free these structures all the time,
* we pre-allocate a small set of them within the ber element structure.
* thus we need to spot when we've overflowed this stack and fall back to
* malloc'ing instead.
*/
static int
{
/* can we fit into the local stack ? */
/* yes */
} else {
/* no */
== NULLSEQORSET) {
return (-1);
}
}
else
/* Set aside room for a 4 byte length field */
return (-1);
}
return (0);
}
static int
{
if (tag == KMFBER_DEFAULT)
}
static int
{
if (tag == KMFBER_DEFAULT)
}
static int
{
/*
* If this is the toplevel sequence or set, we need to actually
* write the stuff out. Otherwise, it's already been put in
* the appropriate buffer and will be written when the toplevel
* one is written. In this case all we need to do is update the
* length and tag.
*/
} else {
}
/* write the tag */
return (-1);
/* Write the length in the minimum # of octets */
return (-1);
if (lenlen != FOUR_BYTE_LEN) {
/*
* We set aside FOUR_BYTE_LEN bytes for
* the length field. Move the data if
* we don't actually need that much
*/
FOUR_BYTE_LEN, len);
}
} else {
/* Fill FOUR_BYTE_LEN bytes for length field */
/* one byte of length length */
return (-1);
/* the length itself */
if (kmfber_write(ber,
FOUR_BYTE_LEN - 1)
return (-1);
}
} else {
/* the tag */
}
/* one byte of length length */
if (lenlen > 1) {
/* Write the length itself */
(char *)&netlen + sizeof (ber_uint_t) -
(lenlen - 1),
lenlen - 1);
}
if (lenlen != FOUR_BYTE_LEN) {
/*
* We set aside FOUR_BYTE_LEN bytes for
* the length field. Move the data if
* we don't actually need that much
*/
FOUR_BYTE_LEN, len);
}
} else {
/* the length itself */
}
}
/* we're done with this seqorset, so free it up */
/* was this one from the local stack ? */
}
}
/* VARARGS */
int
{
char *s, **ss;
int rc, i, t;
#ifdef KMFBER_DEBUG
if (lber_debug & 64) {
char msg[80];
}
#endif
switch (*fmt) {
case 'b': /* boolean */
break;
case 'i': /* int */
break;
case 'D': /* Object ID */
break;
break;
case 'I': /* int */
break;
case 'e': /* enumeration */
break;
case 'l':
break;
case 'n': /* null */
break;
case 'o': /* octet string (non-null terminated) */
break;
case 's': /* string */
break;
case 'B': /* bit string */
break;
case 't': /* tag for the next element */
break;
case 'T': /* Write an explicit tag, but don't change current */
break;
case 'v': /* vector of strings */
break;
break;
}
break;
case 'V': /* sequences of strings + lengths */
break;
break;
}
break;
case '{': /* begin sequence */
break;
case '}': /* end sequence */
break;
case '[': /* begin set */
break;
case ']': /* end set */
break;
default: {
#ifdef KMFBER_DEBUG
char msg[80];
#endif
rc = -1;
break;
}
}
if (ber->ber_usertag == 0)
else
ber->ber_usertag = 0;
}
return (rc);
}