/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
PRBool isExplicit, /* we are handling an isExplicit header */
indefinite, /* need end-of-contents */
is_string, /* encoding a simple string or an ANY */
may_stream, /* when streaming, do indefinite encoding */
optional, /* omit field if it has no contents */
disallowStreaming; /* disallow streaming in all sub-templates */
} sec_asn1e_state;
subt = SEC_ASN1GetSubtemplate(state->theTemplate, state->src, PR_TRUE); if (isInline && optional) { /* we only handle a very limited set of optional inline cases at
this time */ if (PR_FALSE != SEC_ASN1IsTemplateSimple(subt)) { /* we now know that the target is a SECItem*, so we can check
if the source contains one */
SECItem *target = (SECItem *)state->src; if (!target || !target->data || !target->len) { /* no valid data to encode subtemplate */ return state;
}
} else {
PORT_Assert(0); /* complex templates are not handled as
inline optional */
}
}
state = sec_asn1e_push_state(state->top, subt, src, PR_FALSE); if (state == NULL) return state;
if (universal) { /* *ThisisaPOINTERorINLINE;justinitbasedonthat *andwearedone.
*/ return sec_asn1e_init_state_based_on_template(state);
}
is_string = PR_FALSE; switch (under_kind & SEC_ASN1_TAGNUM_MASK) { case SEC_ASN1_SET: /* *XXXAplainoldSET(asopposedtoaSETOF)isnotimplemented. *Ifiteveris,removethisassert...
*/
PORT_Assert((under_kind & SEC_ASN1_GROUP) != 0); /* fallthru */ case SEC_ASN1_SEQUENCE:
tag_modifiers |= SEC_ASN1_CONSTRUCTED; break; case SEC_ASN1_BIT_STRING: case SEC_ASN1_BMP_STRING: case SEC_ASN1_GENERALIZED_TIME: case SEC_ASN1_IA5_STRING: case SEC_ASN1_OCTET_STRING: case SEC_ASN1_PRINTABLE_STRING: case SEC_ASN1_T61_STRING: case SEC_ASN1_UNIVERSAL_STRING: case SEC_ASN1_UTC_TIME: case SEC_ASN1_UTF8_STRING: case SEC_ASN1_VISIBLE_STRING: /* *Wedonotyetknowifwewillbeconstructingthestring, *sowehavetowaittodothisfinaltagmodification.
*/
is_string = PR_TRUE; break;
}
}
if ((encode_kind & (SEC_ASN1_POINTER | SEC_ASN1_INLINE)) || !universal) { /* XXX any bits we want to disallow (PORT_Assert against) here? */
theTemplate = SEC_ASN1GetSubtemplate(theTemplate, src, PR_TRUE); if (encode_kind & SEC_ASN1_POINTER) {
src = *(void **)src; if (src == NULL) {
*pHdrException = optional ? hdr_optional : hdr_normal; return0;
}
} elseif (encode_kind & SEC_ASN1_INLINE) { /* check that there are no extraneous bits */ if (optional) { if (PR_FALSE != SEC_ASN1IsTemplateSimple(theTemplate)) { /* we now know that the target is a SECItem*, so we can check
if the source contains one */
SECItem *target = (SECItem *)src; if (!target || !target->data || !target->len) { /* no valid data to encode subtemplate */
*pHdrException = hdr_optional; return0;
}
} else {
PORT_Assert(0); /* complex templates not handled as inline
optional */
}
}
}
src = (char *)src + theTemplate->offset;
/* recurse to find the length of the subtemplate */
len = sec_asn1e_contents_length(theTemplate, src, disallowStreaming,
insideIndefinite, pHdrException); if (len == 0 && optional) {
*pHdrException = hdr_optional;
} elseif (isExplicit) { if (*pHdrException == hdr_any) { /* *we* do not want to add in a header, **butourcallerstilldoes.
*/
*pHdrException = hdr_normal;
} elseif (*pHdrException == hdr_normal) { /* if the inner content exists, our length is *len(identifier)+len(length)+len(innercontent) *XXXwecurrentlyassumelen(identifier)==1; *tosupportahigh-tag-numberthiswouldneedtobesmarter.
*/
len += 1 + SEC_ASN1LengthLength(len);
}
} return len;
}
underlying_kind = encode_kind;
/* This is only used in decoding; it plays no part in encoding. */ if (underlying_kind & SEC_ASN1_SAVE) { /* check that there are no extraneous bits */
PORT_Assert(underlying_kind == SEC_ASN1_SAVE);
*pHdrException = hdr_decoder; return0;
}
/* Having any of these bits is not expected here... */
PORT_Assert((underlying_kind & UNEXPECTED_FLAGS) == 0);
underlying_kind &= ~UNEXPECTED_FLAGS; #undef UNEXPECTED_FLAGS
if (underlying_kind & SEC_ASN1_CHOICE) { void *src2; int indx = sec_asn1e_which_choice(src, theTemplate); if (0 == indx) { /* XXX set an error? "choice not found" */ /* state->top->status = encodeError; */ return0;
}
for (; *group != NULL; group++) {
sub_src = (char *)(*group) + tmpt->offset;
sub_len = sec_asn1e_contents_length(tmpt, sub_src,
disallowStreaming,
insideIndefinite,
pHdrException);
len += sub_len; /* *XXXThe1belowisthepresumedlengthoftheidentifier; *tosupportahigh-tag-numberthiswouldneedtobesmarter.
*/ if (*pHdrException == hdr_normal)
len += 1 + SEC_ASN1LengthLength(sub_len);
}
} break;
case SEC_ASN1_SEQUENCE: case SEC_ASN1_SET: { const SEC_ASN1Template *tmpt; void *sub_src; unsignedlong sub_len;
len = 0; for (tmpt = theTemplate + 1; tmpt->kind; tmpt++) {
sub_src = (char *)src + tmpt->offset;
sub_len = sec_asn1e_contents_length(tmpt, sub_src,
disallowStreaming,
insideIndefinite,
pHdrException);
len += sub_len; /* *XXXThe1belowisthepresumedlengthoftheidentifier; *tosupportahigh-tag-numberthiswouldneedtobesmarter.
*/ if (*pHdrException == hdr_normal)
len += 1 + SEC_ASN1LengthLength(sub_len);
}
} break;
case SEC_ASN1_BIT_STRING: /* convert bit length to byte */
len = (((SECItem *)src)->len + 7) >> 3; /* bit string contents involve an extra octet */ if (len)
len++; break;
case SEC_ASN1_INTEGER: /* ASN.1 INTEGERs are signed. *Ifthesourceisanunsignedinteger,theencoderwillneed *tohandletheconversionhere.
*/
{ unsignedchar *buf = ((SECItem *)src)->data;
SECItemType integerType = ((SECItem *)src)->type;
len = ((SECItem *)src)->len; while (len > 0) { if (*buf != 0) { if (*buf & 0x80 && integerType == siUnsignedInteger) {
len++; /* leading zero needed to make number signed */
} break; /* reached beginning of number */
} if (len == 1) { break; /* the number 0 */
} if (buf[1] & 0x80) { break; /* leading zero already present */
} /* extraneous leading zero, keep going */
buf++;
len--;
}
} break;
case SEC_ASN1_NULL:
len = 0; break;
default:
len = ((SECItem *)src)->len; break;
} /* end switch */
#ifndef WHAT_PROBLEM_DOES_THIS_SOLVE /* if we're streaming, we may have a secitem w/len 0 as placeholder */ if (!len && insideIndefinite && may_stream && !disallowStreaming) {
len = 1;
} #endif
} /* end else */
if (state->underlying_kind == SEC_ASN1_ANY) {
state->place = duringContents; return;
}
if (state->underlying_kind & SEC_ASN1_CHOICE) { int indx = sec_asn1e_which_choice(state->src, state->theTemplate); if (0 == indx) { /* XXX set an error? "choice not found" */
state->top->status = encodeError; return;
}
state->place = afterChoice;
state = sec_asn1e_push_state(state->top, &state->theTemplate[indx],
(char *)state->src - state->theTemplate->offset,
PR_TRUE); if (state) { /* *Dothe"before"fieldnotification.
*/
sec_asn1e_notify_before(state->top, state->src, state->depth);
(void)sec_asn1e_init_state_based_on_template(state);
} return;
}
/* The !isString test below is apparently intended to ensure that all **constructedtypesreceiveindefinitelengthencoding.
*/
indefinite = (PRBool)(state->top->streaming && state->may_stream &&
(state->top->from_buf || !state->is_string));
/* *Ifwearedoingadefinite-lengthencoding,firstwehaveto *walkthedatastructuretocalculatetheentirecontentslength. *Ifwearedoinganindefinite-lengthencoding,westillneedto *knowifthecontentsis: *optionalandtobeomitted,or *anANY(headerispre-encoded),or *aSAVEorsomeotherkindoftemplateusedonlybythedecoder. *So,wecallthisfunctioneitherway.
*/
contents_length = sec_asn1e_contents_length(state->theTemplate,
state->src,
state->disallowStreaming,
indefinite,
&hdrException); /* *Wemightbetoldexplicitlynottoputoutaheader. *Butitcanalsobethecase,viaapushedsubtemplate,that *sec_asn1e_contents_lengthcouldnotknowthatthisfieldis *reallyoptional.Socheckforthatexplicitly,too.
*/ if (hdrException != hdr_normal ||
(contents_length == 0 && state->optional)) {
state->place = afterContents; if (state->top->streaming &&
state->may_stream &&
state->top->from_buf) { /* we did not find an optional indefinite string, so we *don'tencodeit.However,ifTakeFromBufison,westop *hereanywaytogiveourcallerachancetointerceptatthe *samepointwherewewouldstopifthefieldwerepresent.
*/
state->top->status = needBytes;
} return;
}
if (cx->status == needBytes) {
cx->status = keepGoing;
}
while (cx->status == keepGoing) {
state = cx->current; switch (state->place) { case beforeHeader:
sec_asn1e_write_header(state); break; case duringContents: if (cx->from_buf)
sec_asn1e_write_contents_from_buf(state, buf, len); else
sec_asn1e_write_contents(state); break; case duringGroup:
sec_asn1e_next_in_group(state); break; case duringSequence:
sec_asn1e_next_in_sequence(state); break; case afterContents:
sec_asn1e_after_contents(state); break; case afterImplicit: case afterInline: case afterPointer: case afterChoice: /* *Thesestatesaremoredocumentationthananything. *Theyjustneedtoforceapop.
*/
PORT_Assert(!state->indefinite);
state->place = afterContents; break; case notInUse: default: /* This is not an error, but rather a plain old BUG! */
PORT_Assert(0);
cx->status = encodeError; break;
}
if (cx->status == encodeError) break;
/* It might have changed, so we have to update our local copy. */
state = cx->current;
/* If it is NULL, we have popped all the way to the top. */ if (state == NULL) {
cx->status = allDone; break;
}
}
if (cx->status == encodeError) { return SECFailure;
}
void
SEC_ASN1EncoderClearTakeFromBuf(SEC_ASN1EncoderContext *cx)
{ /* we should actually be taking from buf *now* */
PORT_Assert(cx->from_buf); if (!cx->from_buf) /* if not, just do nothing */ return;
/* XXX depth and data_kind are unused; is there a PC way to silence warnings? */ staticvoid
sec_asn1e_encode_item_store(void *arg, constchar *buf, unsignedlong len, int depth, SEC_ASN1EncodingPart data_kind)
{
SECItem *dest;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.