/* 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/. */
struct NSSCMSEncoderContextStr {
SEC_ASN1EncoderContext *ecx; /* ASN.1 encoder context */
PRBool ecxupdated; /* true if data was handed in */
NSSCMSMessage *cmsg; /* pointer to the root message */
SECOidTag type; /* type tag of the current content */
NSSCMSContent content; /* pointer to current content */ struct nss_cms_encoder_output output; /* output function */ int error; /* error code */
NSSCMSEncoderContext *childp7ecx; /* link to child encoder context */
};
#ifdef CMSDEBUG
fprintf(stderr, "%6.6s, dest = 0x%08x, depth = %d\n", before ? "before" : "after",
dest, depth); #endif
/* *Watchforthecontentfield,atwhichpointwewanttoinstruct *theASN.1encodertostarttakingbytesfromthebuffer.
*/ if (NSS_CMSType_IsData(p7ecx->type)) {
cinfo = NSS_CMSContent_GetContentInfo(p7ecx->content.pointer, p7ecx->type); if (before && dest == &(cinfo->rawContent)) { /* just set up encoder to grab from user - no encryption or digesting */ if ((item = cinfo->content.data) != NULL)
(void)nss_cms_encoder_work_data(p7ecx, NULL, item->data,
item->len, PR_TRUE, PR_TRUE); else
SEC_ASN1EncoderSetTakeFromBuf(p7ecx->ecx);
SEC_ASN1EncoderClearNotifyProc(p7ecx->ecx); /* no need to get notified anymore */
}
} elseif (NSS_CMSType_IsWrapper(p7ecx->type)) { /* when we know what the content is, we encode happily until we reach the inner content */
cinfo = NSS_CMSContent_GetContentInfo(p7ecx->content.pointer, p7ecx->type);
childtype = NSS_CMSContentInfo_GetContentTypeTag(cinfo);
if (after && dest == &(cinfo->contentType)) { /* we're right before encoding the data (if we have some or not) */ /* (for encrypted data, we're right before the contentEncAlg which may change */ /* in nss_cms_before_data because of IV calculation when setting up encryption) */ if (nss_cms_before_data(p7ecx) != SECSuccess)
p7ecx->error = PORT_GetError();
} if (before && dest == &(cinfo->rawContent)) { if (p7ecx->childp7ecx == NULL) { if ((NSS_CMSType_IsData(childtype) && (item = cinfo->content.data) != NULL)) { /* we are the innermost non-data and we have data - feed it in */
(void)nss_cms_encoder_work_data(p7ecx, NULL, item->data,
item->len, PR_TRUE, PR_TRUE);
} else { /* else we'll have to get data from user */
SEC_ASN1EncoderSetTakeFromBuf(p7ecx->ecx);
}
} else { /* if we have a nested encoder, wait for its data */
SEC_ASN1EncoderSetTakeFromBuf(p7ecx->ecx);
}
} if (after && dest == &(cinfo->rawContent)) { if (nss_cms_after_data(p7ecx) != SECSuccess)
p7ecx->error = PORT_GetError();
SEC_ASN1EncoderClearNotifyProc(p7ecx->ecx); /* no need to get notified anymore */
}
} else { /* we're still in the root message */ if (after && dest == &(rootcinfo->contentType)) { /* got the content type OID now - so find out the type tag */
p7ecx->type = NSS_CMSContentInfo_GetContentTypeTag(rootcinfo); /* set up a pointer to our current content */
p7ecx->content = rootcinfo->content;
}
}
}
/* call _Encode_BeforeData handlers */ switch (p7ecx->type) { case SEC_OID_PKCS7_SIGNED_DATA: /* we're encoding a signedData, so set up the digests */
rv = NSS_CMSSignedData_Encode_BeforeData(p7ecx->content.signedData); break; case SEC_OID_PKCS7_DIGESTED_DATA: /* we're encoding a digestedData, so set up the digest */
rv = NSS_CMSDigestedData_Encode_BeforeData(p7ecx->content.digestedData); break; case SEC_OID_PKCS7_ENVELOPED_DATA:
rv = NSS_CMSEnvelopedData_Encode_BeforeData(p7ecx->content.envelopedData); break; case SEC_OID_PKCS7_ENCRYPTED_DATA:
rv = NSS_CMSEncryptedData_Encode_BeforeData(p7ecx->content.encryptedData); break; default: if (NSS_CMSType_IsWrapper(p7ecx->type)) {
rv = NSS_CMSGenericWrapperData_Encode_BeforeData(p7ecx->type,
p7ecx->content.genericData);
} else {
rv = SECFailure;
}
} if (rv != SECSuccess) return SECFailure;
/* ok, now we have a pointer to cinfo */ /* find out what kind of data is encapsulated */
if (NSS_CMSType_IsWrapper(childtype)) { /* in these cases, we need to set up a child encoder! */ /* create new encoder context */
childp7ecx = PORT_ZAlloc(sizeof(NSSCMSEncoderContext)); if (childp7ecx == NULL) return SECFailure;
/* the CHILD encoder needs to hand its encoded data to the CURRENT encoder *(whichwillencryptand/ordigestit) *thisneedstoroutebackintoourupdatefunction
* which finds the lowest encoding context & encrypts and computes digests */
childp7ecx->type = childtype;
childp7ecx->content = cinfo->content; /* use the non-recursive update function here, of course */
childp7ecx->output.outputfn = (NSSCMSContentCallback)nss_cms_encoder_update;
childp7ecx->output.outputarg = p7ecx;
childp7ecx->output.destpoolp = NULL;
childp7ecx->output.dest = NULL;
childp7ecx->cmsg = p7ecx->cmsg;
childp7ecx->ecxupdated = PR_FALSE;
childp7ecx->childp7ecx = NULL;
/* now initialize the data for encoding the first third */ switch (childp7ecx->type) { case SEC_OID_PKCS7_SIGNED_DATA:
rv = NSS_CMSSignedData_Encode_BeforeStart(cinfo->content.signedData); break; case SEC_OID_PKCS7_ENVELOPED_DATA:
rv = NSS_CMSEnvelopedData_Encode_BeforeStart(cinfo->content.envelopedData); break; case SEC_OID_PKCS7_DIGESTED_DATA:
rv = NSS_CMSDigestedData_Encode_BeforeStart(cinfo->content.digestedData); break; case SEC_OID_PKCS7_ENCRYPTED_DATA:
rv = NSS_CMSEncryptedData_Encode_BeforeStart(cinfo->content.encryptedData); break; default:
rv = NSS_CMSGenericWrapperData_Encode_BeforeStart(childp7ecx->type,
cinfo->content.genericData); break;
} if (rv != SECSuccess) goto loser;
/* please note that we are NOT calling SEC_ASN1EncoderUpdate here to kick off the */ /* encoding process - we'll do that from the update function instead */ /* otherwise we'd be encoding data from a call of the notify function of the */ /* parent encoder (which would not work) */
} elseif (NSS_CMSType_IsData(childtype)) {
p7ecx->childp7ecx = NULL;
} else { /* we do not know this type */
p7ecx->error = SEC_ERROR_BAD_DER;
}
return SECSuccess;
loser: if (childp7ecx) { if (childp7ecx->ecx)
SEC_ASN1EncoderFinish(childp7ecx->ecx);
PORT_Free(childp7ecx);
p7ecx->childp7ecx = NULL;
} return SECFailure;
}
/* we got data (either from the caller, or from a lower level encoder) */
cinfo = NSS_CMSContent_GetContentInfo(p7ecx->content.pointer, p7ecx->type); if (!cinfo) { /* The original programmer didn't expect this to happen */
p7ecx->error = SEC_ERROR_LIBRARY_FAILURE; return SECFailure;
}
/* Update the running digest. */ if (len && cinfo->privateInfo && cinfo->privateInfo->digcx != NULL)
NSS_CMSDigestContext_Update(cinfo->privateInfo->digcx, data, len);
/* Encrypt this chunk. */ if (cinfo->privateInfo && cinfo->privateInfo->ciphcx != NULL) { unsignedint inlen; /* length of data being encrypted */ unsignedint outlen; /* length of encrypted data */ unsignedint buflen; /* length available for encrypted data */
tag = NSS_CMSContentInfo_GetContentTypeTag(cinfo); switch (tag) { case SEC_OID_PKCS7_SIGNED_DATA:
rv = NSS_CMSSignedData_Encode_BeforeStart(cinfo->content.signedData); break; case SEC_OID_PKCS7_ENVELOPED_DATA:
rv = NSS_CMSEnvelopedData_Encode_BeforeStart(cinfo->content.envelopedData); break; case SEC_OID_PKCS7_DIGESTED_DATA:
rv = NSS_CMSDigestedData_Encode_BeforeStart(cinfo->content.digestedData); break; case SEC_OID_PKCS7_ENCRYPTED_DATA:
rv = NSS_CMSEncryptedData_Encode_BeforeStart(cinfo->content.encryptedData); break; default: if (NSS_CMSType_IsWrapper(tag)) {
rv = NSS_CMSGenericWrapperData_Encode_BeforeStart(tag,
p7ecx->content.genericData);
} else {
rv = SECFailure;
} break;
} if (rv != SECSuccess) {
PORT_Free(p7ecx); return NULL;
}
/* Initialize the BER encoder.
* Note that this will not encode anything until the first call to SEC_ASN1EncoderUpdate */
p7ecx->ecx = SEC_ASN1EncoderStart(cmsg, NSSCMSMessageTemplate,
nss_cms_encoder_out, &(p7ecx->output)); if (p7ecx->ecx == NULL) {
PORT_Free(p7ecx); return NULL;
}
p7ecx->ecxupdated = PR_FALSE;
/* *Indicatethatwearestreaming.Wewillbestreaminguntilwe *getpastthecontentsbytes.
*/ if (!cinfo->privateInfo || !cinfo->privateInfo->dontStream)
SEC_ASN1EncoderSetStreaming(p7ecx->ecx);
/* this will kick off the encoding process & encode everything up to the content bytes, *atwhichpointthenotifyfunctionsetsstreamingmode(andpossiblycreates
* a child encoder). */
p7ecx->ecxupdated = PR_TRUE; if (SEC_ASN1EncoderUpdate(p7ecx->ecx, NULL, 0) != SECSuccess) {
PORT_Free(p7ecx); return NULL;
}
/* hand data to the innermost decoder */ if (p7ecx->childp7ecx) { /* tell the child to start encoding, up to its first data byte, if it
* hasn't started yet */ if (!p7ecx->childp7ecx->ecxupdated) {
p7ecx->childp7ecx->ecxupdated = PR_TRUE; if (SEC_ASN1EncoderUpdate(p7ecx->childp7ecx->ecx, NULL, 0) != SECSuccess) return SECFailure;
} /* recursion here */
rv = NSS_CMSEncoder_Update(p7ecx->childp7ecx, data, len);
} else { /* we are at innermost decoder */ /* find out about our inner content type - must be data */
cinfo = NSS_CMSContent_GetContentInfo(p7ecx->content.pointer, p7ecx->type); if (!cinfo) { /* The original programmer didn't expect this to happen */
p7ecx->error = SEC_ERROR_LIBRARY_FAILURE; return SECFailure;
}
childtype = NSS_CMSContentInfo_GetContentTypeTag(cinfo); if (!NSS_CMSType_IsData(childtype)) return SECFailure; /* and we must not have preset data */ if (cinfo->content.data != NULL) return SECFailure;
/* hand it the data so it can encode it (let DER trickle up the chain) */
rv = nss_cms_encoder_work_data(p7ecx, NULL, (constunsignedchar *)data,
len, PR_FALSE, PR_TRUE);
} return rv;
}
/* kick the encoder back into working mode again. *Weturnoffstreamingstuff(whichwillcausetheencodertocontinue *encodinghappily,nowthatwehaveallthedata(likedigests)readyforit).
*/
SEC_ASN1EncoderClearTakeFromBuf(p7ecx->ecx);
SEC_ASN1EncoderClearStreaming(p7ecx->ecx);
/* now that TakeFromBuf is off, this will kick this encoder to finish encoding */
rv = SEC_ASN1EncoderUpdate(p7ecx->ecx, NULL, 0);
cinfo = NSS_CMSContent_GetContentInfo(p7ecx->content.pointer, p7ecx->type); if (!cinfo) { /* The original programmer didn't expect this to happen */
p7ecx->error = SEC_ERROR_LIBRARY_FAILURE;
rv = SECFailure; goto loser;
}
SEC_ASN1EncoderClearTakeFromBuf(p7ecx->ecx);
SEC_ASN1EncoderClearStreaming(p7ecx->ecx); /* now that TakeFromBuf is off, this will kick this encoder to finish encoding */
rv = SEC_ASN1EncoderUpdate(p7ecx->ecx, NULL, 0);
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.