nssb64e.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 763 行 · 第 1/2 页

C
763
字号
}/* * Function to start a base64 encoding context. * An "output_fn" is required; the "output_arg" parameter to that is optional. * If linebreaks in the encoded output are desired, "line_length" specifies * where to place them -- it will be rounded down to the nearest multiple of 4 * (if it is not already an even multiple of 4).  If it is zero, no linebreaks * will be added.  (FYI, a linebreak is CRLF -- two characters.) */static PLBase64Encoder *PL_CreateBase64Encoder (PRInt32 (*output_fn) (void *, const char *, PRInt32),			void *output_arg, PRUint32 line_length){    PLBase64Encoder *data;    if (output_fn == NULL) {	PR_SetError (PR_INVALID_ARGUMENT_ERROR, 0);	return NULL;    }    data = pl_base64_create_encoder (line_length, NULL, 0);    if (data == NULL)	return NULL;    data->output_fn = output_fn;    data->output_arg = output_arg;    return data;}/* * Push data through the encoder, causing the output_fn (provided to Create) * to be called with the encoded data. */static PRStatusPL_UpdateBase64Encoder (PLBase64Encoder *data, const unsigned char *buffer,			PRUint32 size){    /* XXX Should we do argument checking only in debug build? */    if (data == NULL || buffer == NULL || size == 0) {	PR_SetError (PR_INVALID_ARGUMENT_ERROR, 0);	return PR_FAILURE;    }    return pl_base64_encode_buffer (data, buffer, size);}/* * When you're done encoding, call this to free the data.  If "abort_p" * is false, then calling this may cause the output_fn to be called * one last time (as the last buffered data is flushed out). */static PRStatusPL_DestroyBase64Encoder (PLBase64Encoder *data, PRBool abort_p){    PRStatus status = PR_SUCCESS;    /* XXX Should we do argument checking only in debug build? */    if (data == NULL) {	PR_SetError (PR_INVALID_ARGUMENT_ERROR, 0);	return PR_FAILURE;    }    /* Flush out the last few buffered characters. */    if (!abort_p)	status = pl_base64_encode_flush (data);    if (data->output_buffer != NULL)	PR_Free(data->output_buffer);    PR_Free(data);    return status;}/* * Perform base64 encoding from an input buffer to an output buffer. * The output buffer can be provided (as "dest"); you can also pass in * a NULL and this function will allocate a buffer large enough for you, * and return it.  If you do provide the output buffer, you must also * provide the maximum length of that buffer (as "maxdestlen"). * The actual encoded length of output will be returned to you in * "output_destlen". * * If linebreaks in the encoded output are desired, "line_length" specifies * where to place them -- it will be rounded down to the nearest multiple of 4 * (if it is not already an even multiple of 4).  If it is zero, no linebreaks * will be added.  (FYI, a linebreak is CRLF -- two characters.) * * Return value is NULL on error, the output buffer (allocated or provided) * otherwise. */static char *PL_Base64EncodeBuffer (const unsigned char *src, PRUint32 srclen,		       PRUint32 line_length, char *dest, PRUint32 maxdestlen,		       PRUint32 *output_destlen){    PRUint32 need_length;    PLBase64Encoder *data = NULL;    PRStatus status;    PR_ASSERT(srclen > 0);    if (srclen == 0)	return dest;    /*     * How much space could we possibly need for encoding this input?     */    need_length = PL_Base64MaxEncodedLength (srclen, line_length);    /*     * Make sure we have at least that much, if output buffer provided.     */    if (dest != NULL) {	PR_ASSERT(maxdestlen >= need_length);	if (maxdestlen < need_length) {	    PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0);	    return NULL;	}    } else {	maxdestlen = need_length;    }    data = pl_base64_create_encoder(line_length, dest, maxdestlen);    if (data == NULL)	return NULL;    status = pl_base64_encode_buffer (data, src, srclen);    /*     * We do not wait for Destroy to flush, because Destroy will also     * get rid of our encoder context, which we need to look at first!     */    if (status == PR_SUCCESS)	status = pl_base64_encode_flush (data);    if (status != PR_SUCCESS) {	(void) PL_DestroyBase64Encoder (data, PR_TRUE);	return NULL;    }    dest = data->output_buffer;    /* Must clear this or Destroy will free it. */    data->output_buffer = NULL;    *output_destlen = data->output_length;    status = PL_DestroyBase64Encoder (data, PR_FALSE);    if (status == PR_FAILURE) {	PR_Free(dest);	return NULL;    }    return dest;}/* * XXX End of base64 encoding code to be moved into NSPR. ******************************************************** *//* * This is the beginning of the NSS cover functions.  These will * provide the interface we want to expose as NSS-ish.  For example, * they will operate on our Items, do any special handling or checking * we want to do, etc. */PR_BEGIN_EXTERN_C/* * A boring cover structure for now.  Perhaps someday it will include * some more interesting fields. */struct NSSBase64EncoderStr {    PLBase64Encoder *pl_data;};PR_END_EXTERN_C/* * Function to start a base64 encoding context. */NSSBase64Encoder *NSSBase64Encoder_Create (PRInt32 (*output_fn) (void *, const char *, PRInt32),			 void *output_arg){    PLBase64Encoder *pl_data;    NSSBase64Encoder *nss_data;    nss_data = PORT_ZNew(NSSBase64Encoder);    if (nss_data == NULL)	return NULL;    pl_data = PL_CreateBase64Encoder (output_fn, output_arg, 64);    if (pl_data == NULL) {	PORT_Free(nss_data);	return NULL;    }    nss_data->pl_data = pl_data;    return nss_data;}/* * Push data through the encoder, causing the output_fn (provided to Create) * to be called with the encoded data. */SECStatusNSSBase64Encoder_Update (NSSBase64Encoder *data, const unsigned char *buffer,			 PRUint32 size){    PRStatus pr_status;    /* XXX Should we do argument checking only in debug build? */    if (data == NULL) {	PORT_SetError (SEC_ERROR_INVALID_ARGS);	return SECFailure;    }    pr_status = PL_UpdateBase64Encoder (data->pl_data, buffer, size);    if (pr_status == PR_FAILURE)	return SECFailure;    return SECSuccess;}/* * When you're done encoding, call this to free the data.  If "abort_p" * is false, then calling this may cause the output_fn to be called * one last time (as the last buffered data is flushed out). */SECStatusNSSBase64Encoder_Destroy (NSSBase64Encoder *data, PRBool abort_p){    PRStatus pr_status;    /* XXX Should we do argument checking only in debug build? */    if (data == NULL) {	PORT_SetError (SEC_ERROR_INVALID_ARGS);	return SECFailure;    }    pr_status = PL_DestroyBase64Encoder (data->pl_data, abort_p);    PORT_Free(data);    if (pr_status == PR_FAILURE)	return SECFailure;    return SECSuccess;}/* * Perform base64 encoding of binary data "inItem" to an ascii string. * The output buffer may be provided (as "outStrOpt"); you can also pass * in a NULL and the buffer will be allocated for you.  The result will * be null-terminated, and if the buffer is provided, "maxOutLen" must * specify the maximum length of the buffer and will be checked to * supply sufficient space space for the encoded result.  (If "outStrOpt" * is NULL, "maxOutLen" is ignored.) * * If "outStrOpt" is NULL, allocation will happen out of the passed-in * "arenaOpt", if *it* is non-NULL, otherwise standard allocation (heap) * will be used. * * Return value is NULL on error, the output buffer (allocated or provided) * otherwise. */char *NSSBase64_EncodeItem (PRArenaPool *arenaOpt, char *outStrOpt,		      unsigned int maxOutLen, SECItem *inItem){    char *out_string = outStrOpt;    PRUint32 max_out_len;    PRUint32 out_len;    void *mark = NULL;    char *dummy;    PORT_Assert(inItem != NULL && inItem->data != NULL && inItem->len != 0);    if (inItem == NULL || inItem->data == NULL || inItem->len == 0) {	PORT_SetError (SEC_ERROR_INVALID_ARGS);	return NULL;    }    max_out_len = PL_Base64MaxEncodedLength (inItem->len, 64);    if (arenaOpt != NULL)	mark = PORT_ArenaMark (arenaOpt);    if (out_string == NULL) {	if (arenaOpt != NULL)	    out_string = PORT_ArenaAlloc (arenaOpt, max_out_len + 1);	else	    out_string = PORT_Alloc (max_out_len + 1);	if (out_string == NULL) {	    if (arenaOpt != NULL)		PORT_ArenaRelease (arenaOpt, mark);	    return NULL;	}    } else {	if ((max_out_len + 1) > maxOutLen) {	    PORT_SetError (SEC_ERROR_OUTPUT_LEN);	    return NULL;	}	max_out_len = maxOutLen;    }    dummy = PL_Base64EncodeBuffer (inItem->data, inItem->len, 64,				   out_string, max_out_len, &out_len);    if (dummy == NULL) {	if (arenaOpt != NULL) {	    PORT_ArenaRelease (arenaOpt, mark);	} else {	    PORT_Free (out_string);	}	return NULL;    }    if (arenaOpt != NULL)	PORT_ArenaUnmark (arenaOpt, mark);    out_string[out_len] = '\0';    return out_string;}/* * XXX Everything below is deprecated.  If you add new stuff, put it * *above*, not below. *//* * XXX The following "BTOA" functions are provided for backward compatibility * with current code.  They should be considered strongly deprecated. * When we can convert all our code over to using the new NSSBase64Encoder_ * functions defined above, we should get rid of these altogether.  (Remove * protoypes from base64.h as well -- actually, remove that file completely). * If someone thinks either of these functions provides such a very useful * interface (though, as shown, the same functionality can already be * obtained by calling NSSBase64_EncodeItem directly), fine -- but then * that API should be provided with a nice new NSSFoo name and using * appropriate types, etc. */#include "base64.h"/*** Return an PORT_Alloc'd ascii string which is the base64 encoded** version of the input string.*/char *BTOA_DataToAscii(const unsigned char *data, unsigned int len){    SECItem binary_item;    binary_item.data = (unsigned char *)data;    binary_item.len = len;    return NSSBase64_EncodeItem (NULL, NULL, 0, &binary_item);}/*** Convert from binary encoding of an item to ascii.*/char *BTOA_ConvertItemToAscii (SECItem *binary_item){    return NSSBase64_EncodeItem (NULL, NULL, 0, binary_item);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?