Committing in NSSBranch.
Modified Files: derdec.c For Bug 352929 Reviewed by Wan-Teh Chang and Nelson Removed DER_Decode and der_decode functions git-svn-id: svn://10.0.0.236/trunk@236980 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -213,340 +213,6 @@ der_capture(unsigned char *buf, unsigned char *end,
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
der_decode(PRArenaPool *arena, void *dest, DERTemplate *dtemplate,
|
||||
unsigned char *buf, int header_len, PRUint32 contents_len)
|
||||
{
|
||||
unsigned char *orig_buf, *end;
|
||||
unsigned long encode_kind, under_kind;
|
||||
PRBool explicit, optional, universal, check_tag;
|
||||
SECItem *item;
|
||||
SECStatus rv;
|
||||
PRBool indefinite_length, explicit_indefinite_length;
|
||||
|
||||
encode_kind = dtemplate->kind;
|
||||
explicit = (encode_kind & DER_EXPLICIT) ? PR_TRUE : PR_FALSE;
|
||||
optional = (encode_kind & DER_OPTIONAL) ? PR_TRUE : PR_FALSE;
|
||||
universal = ((encode_kind & DER_CLASS_MASK) == DER_UNIVERSAL)
|
||||
? PR_TRUE : PR_FALSE;
|
||||
|
||||
PORT_Assert (!(explicit && universal)); /* bad templates */
|
||||
|
||||
if (header_len == 0) {
|
||||
if (optional || (encode_kind & DER_ANY))
|
||||
return buf;
|
||||
PORT_SetError(SEC_ERROR_BAD_DER);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (encode_kind & DER_POINTER) {
|
||||
void *place, **placep;
|
||||
int offset;
|
||||
|
||||
if (dtemplate->sub != NULL) {
|
||||
dtemplate = dtemplate->sub;
|
||||
under_kind = dtemplate->kind;
|
||||
if (universal) {
|
||||
encode_kind = under_kind;
|
||||
}
|
||||
place = PORT_ArenaZAlloc(arena, dtemplate->arg);
|
||||
offset = dtemplate->offset;
|
||||
} else {
|
||||
if (universal) {
|
||||
under_kind = encode_kind & ~DER_POINTER;
|
||||
} else {
|
||||
under_kind = dtemplate->arg;
|
||||
}
|
||||
place = PORT_ArenaZAlloc(arena, sizeof(SECItem));
|
||||
offset = 0;
|
||||
}
|
||||
if (place == NULL) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
return NULL; /* Out of memory */
|
||||
}
|
||||
placep = (void **)dest;
|
||||
*placep = place;
|
||||
dest = (void *)((char *)place + offset);
|
||||
} else if (encode_kind & DER_INLINE) {
|
||||
PORT_Assert (dtemplate->sub != NULL);
|
||||
dtemplate = dtemplate->sub;
|
||||
under_kind = dtemplate->kind;
|
||||
if (universal) {
|
||||
encode_kind = under_kind;
|
||||
}
|
||||
dest = (void *)((char *)dest + dtemplate->offset);
|
||||
} else if (universal) {
|
||||
under_kind = encode_kind;
|
||||
} else {
|
||||
under_kind = dtemplate->arg;
|
||||
}
|
||||
|
||||
orig_buf = buf;
|
||||
end = buf + header_len + contents_len;
|
||||
|
||||
explicit_indefinite_length = PR_FALSE;
|
||||
|
||||
if (explicit) {
|
||||
/*
|
||||
* This tag is expected to match exactly.
|
||||
* (The template has all of the bits specified.)
|
||||
*/
|
||||
if (*buf != (encode_kind & DER_TAG_MASK)) {
|
||||
if (optional)
|
||||
return buf;
|
||||
PORT_SetError(SEC_ERROR_BAD_DER);
|
||||
return NULL;
|
||||
}
|
||||
if ((header_len == 2) && (*(buf + 1) == 0x80))
|
||||
explicit_indefinite_length = PR_TRUE;
|
||||
buf += header_len;
|
||||
rv = der_capture (buf, end, &header_len, &contents_len);
|
||||
if (rv != SECSuccess)
|
||||
return NULL;
|
||||
if (header_len == 0) { /* XXX is this right? */
|
||||
PORT_SetError(SEC_ERROR_BAD_DER);
|
||||
return NULL;
|
||||
}
|
||||
optional = PR_FALSE; /* can no longer be optional */
|
||||
encode_kind = under_kind;
|
||||
}
|
||||
|
||||
check_tag = PR_TRUE;
|
||||
if (encode_kind & (DER_DERPTR | DER_ANY | DER_FORCE | DER_SKIP)) {
|
||||
PORT_Assert ((encode_kind & DER_ANY) || !optional);
|
||||
encode_kind = encode_kind & (~DER_FORCE);
|
||||
under_kind = under_kind & (~DER_FORCE);
|
||||
check_tag = PR_FALSE;
|
||||
}
|
||||
|
||||
if (check_tag) {
|
||||
PRBool wrong;
|
||||
unsigned char expect_tag, expect_num;
|
||||
|
||||
/*
|
||||
* This tag is expected to match, but the simple types
|
||||
* may or may not have the constructed bit set, so we
|
||||
* have to have all this extra logic.
|
||||
*/
|
||||
wrong = PR_TRUE;
|
||||
expect_tag = (unsigned char)encode_kind & DER_TAG_MASK;
|
||||
expect_num = expect_tag & DER_TAGNUM_MASK;
|
||||
if (expect_num == DER_SET || expect_num == DER_SEQUENCE) {
|
||||
if (*buf == (expect_tag | DER_CONSTRUCTED))
|
||||
wrong = PR_FALSE;
|
||||
} else {
|
||||
if (*buf == expect_tag)
|
||||
wrong = PR_FALSE;
|
||||
else if (*buf == (expect_tag | DER_CONSTRUCTED))
|
||||
wrong = PR_FALSE;
|
||||
}
|
||||
if (wrong) {
|
||||
if (optional)
|
||||
return buf;
|
||||
PORT_SetError(SEC_ERROR_BAD_DER);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (under_kind & DER_DERPTR) {
|
||||
item = (SECItem *)dest;
|
||||
if (under_kind & DER_OUTER) {
|
||||
item->data = buf;
|
||||
item->len = header_len + contents_len;
|
||||
} else {
|
||||
item->data = buf + header_len;
|
||||
item->len = contents_len;
|
||||
}
|
||||
return orig_buf;
|
||||
}
|
||||
|
||||
if (encode_kind & DER_ANY) {
|
||||
contents_len += header_len;
|
||||
header_len = 0;
|
||||
}
|
||||
|
||||
if ((header_len == 2) && (*(buf + 1) == 0x80))
|
||||
indefinite_length = PR_TRUE;
|
||||
else
|
||||
indefinite_length = PR_FALSE;
|
||||
|
||||
buf += header_len;
|
||||
|
||||
if (contents_len == 0)
|
||||
return buf;
|
||||
|
||||
under_kind &= ~DER_OPTIONAL;
|
||||
|
||||
if (under_kind & DER_INDEFINITE) {
|
||||
int count, thing_size;
|
||||
unsigned char *sub_buf;
|
||||
DERTemplate *tmpt;
|
||||
void *things, **indp, ***placep;
|
||||
|
||||
under_kind &= ~DER_INDEFINITE;
|
||||
|
||||
/*
|
||||
* Count items.
|
||||
*/
|
||||
count = 0;
|
||||
sub_buf = buf;
|
||||
while (sub_buf < end) {
|
||||
if (indefinite_length && sub_buf[0] == 0 && sub_buf[1] == 0) {
|
||||
break;
|
||||
}
|
||||
rv = der_capture (sub_buf, end, &header_len, &contents_len);
|
||||
if (rv != SECSuccess)
|
||||
return NULL;
|
||||
count++;
|
||||
sub_buf += header_len + contents_len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate an array of pointers to items; extra one is for a NULL.
|
||||
*/
|
||||
indp = (void**)PORT_ArenaZAlloc(arena, (count + 1) * sizeof(void *));
|
||||
if (indp == NULL) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepare.
|
||||
*/
|
||||
if (under_kind == DER_SET || under_kind == DER_SEQUENCE) {
|
||||
tmpt = dtemplate->sub;
|
||||
PORT_Assert (tmpt != NULL);
|
||||
thing_size = tmpt->arg;
|
||||
PORT_Assert (thing_size != 0);
|
||||
} else {
|
||||
tmpt = NULL;
|
||||
thing_size = sizeof(SECItem);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate the items themselves.
|
||||
*/
|
||||
things = PORT_ArenaZAlloc(arena, count * thing_size);
|
||||
if (things == NULL) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
placep = (void ***)dest;
|
||||
*placep = indp;
|
||||
|
||||
while (count) {
|
||||
/* ignore return value because we already did whole thing above */
|
||||
(void) der_capture (buf, end, &header_len, &contents_len);
|
||||
if (tmpt != NULL) {
|
||||
void *sub_thing;
|
||||
|
||||
sub_thing = (void *)((char *)things + tmpt->offset);
|
||||
buf = der_decode (arena, sub_thing, tmpt,
|
||||
buf, header_len, contents_len);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
} else {
|
||||
item = (SECItem *)things;
|
||||
if (under_kind == DER_ANY) {
|
||||
contents_len += header_len;
|
||||
header_len = 0;
|
||||
}
|
||||
buf += header_len;
|
||||
if (under_kind == DER_BIT_STRING) {
|
||||
item->data = buf + 1;
|
||||
item->len = ((contents_len - 1) << 3) - *buf;
|
||||
} else {
|
||||
item->data = buf;
|
||||
item->len = contents_len;
|
||||
}
|
||||
buf += contents_len;
|
||||
}
|
||||
*indp++ = things;
|
||||
things = (void *)((char *)things + thing_size);
|
||||
count--;
|
||||
}
|
||||
|
||||
*indp = NULL;
|
||||
|
||||
goto der_decode_done;
|
||||
}
|
||||
|
||||
switch (under_kind) {
|
||||
case DER_SEQUENCE:
|
||||
case DER_SET:
|
||||
{
|
||||
DERTemplate *tmpt;
|
||||
void *sub_dest;
|
||||
|
||||
for (tmpt = dtemplate + 1; tmpt->kind; tmpt++) {
|
||||
sub_dest = (void *)((char *)dest + tmpt->offset);
|
||||
rv = der_capture (buf, end, &header_len, &contents_len);
|
||||
if (rv != SECSuccess)
|
||||
return NULL;
|
||||
buf = der_decode (arena, sub_dest, tmpt,
|
||||
buf, header_len, contents_len);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DER_BIT_STRING:
|
||||
item = (SECItem *)dest;
|
||||
item->data = buf + 1;
|
||||
item->len = ((contents_len - 1) << 3) - *buf;
|
||||
buf += contents_len;
|
||||
break;
|
||||
|
||||
case DER_SKIP:
|
||||
buf += contents_len;
|
||||
break;
|
||||
|
||||
default:
|
||||
item = (SECItem *)dest;
|
||||
item->data = buf;
|
||||
item->len = contents_len;
|
||||
buf += contents_len;
|
||||
break;
|
||||
}
|
||||
|
||||
der_decode_done:
|
||||
|
||||
if (indefinite_length && buf[0] == 0 && buf[1] == 0) {
|
||||
buf += 2;
|
||||
}
|
||||
|
||||
if (explicit_indefinite_length && buf[0] == 0 && buf[1] == 0) {
|
||||
buf += 2;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
DER_Decode(PRArenaPool *arena, void *dest, DERTemplate *dtemplate, SECItem *src)
|
||||
{
|
||||
unsigned char *buf;
|
||||
PRUint32 buf_len, contents_len;
|
||||
int header_len;
|
||||
SECStatus rv;
|
||||
|
||||
buf = src->data;
|
||||
buf_len = src->len;
|
||||
|
||||
rv = der_capture (buf, buf + buf_len, &header_len, &contents_len);
|
||||
if (rv != SECSuccess)
|
||||
return rv;
|
||||
|
||||
dest = (void *)((char *)dest + dtemplate->offset);
|
||||
buf = der_decode (arena, dest, dtemplate, buf, header_len, contents_len);
|
||||
if (buf == NULL)
|
||||
return SECFailure;
|
||||
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
DER_Lengths(SECItem *item, int *header_len_p, PRUint32 *contents_len_p)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user