blapi_bsf.c

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

C
2,087
字号
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is the Netscape security libraries. *  * The Initial Developer of the Original Code is Netscape * Communications Corporation.	Portions created by Netscape are  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All * Rights Reserved. *  * Contributor(s): *  * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable  * instead of those above.	If you wish to allow use of your  * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL.  If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. *//*********************************************************************************	Implementation of BLAPI using RSA BSAFE Crypto-C 4.1********************************************************************************//***  Notes:****  1.  SHA1, MD2, and MD5 are not implemented here.  This is because **      BSAFE Crypto-C 4.1 does not provide a mechanism for saving and **      restoring intermediate hash values.  BLAPI uses the functions **      <hash>_Flatten and <hash>_Resurrect to accomplish this, so the **      hashes are implemented elsewhere.****  2.  The DSA and PQG functions which use seeds are not consistent across**      implementations.  In this BSAFE-dependent implementation of BLAPI, **      the seed is understood to be an initial value sent to a random number **      generator used during the key/param generation.  In the implementation**      used by Netscape-branded products, the seed is understood to be actual **      bytes used for the creation of a key or parameters.  This means that **      while the BSAFE-dependent implementation may be self-consistent (using **      the same seed will produce the same key/parameters), it is not **      consistent with the Netscape-branded implementation.  **      Also, according to the BSAFE Crypto-C 4.0 Library Reference Manual, the**      SHA1 Random Number Generator is implemented according to the X9.62**      Draft Standard.  Random number generation in the Netscape-branded**      implementation of BLAPI is compliant with FIPS-186, thus random**      numbers generated using the same seed will differ across **      implementations.****  3.  PQG_VerifyParams is not implemented here.  BSAFE Crypto-C 4.1 **      allows access to the seed and counter values used in generating**      p and q, but does not provide a mechanism for verifying that**      p, q, and g were generated from that seed and counter.  At this**      time, this implementation will set a PR_NOT_IMPLEMENTED_ERROR **      in a call to PQG_VerifyParams.***/#include "prerr.h"#include "secerr.h"/* BSAFE headers */#include "aglobal.h"#include "bsafe.h"/* BLAPI definition */#include "blapi.h"/* default block sizes for algorithms */#define DES_BLOCK_SIZE       8#define RC2_BLOCK_SIZE       8#define RC5_BLOCK_SIZE       8#define MAX_RC5_KEY_BYTES 255#define MAX_RC5_ROUNDS    255#define RC5_VERSION_NUMBER   0x10#define NSS_FREEBL_DEFAULT_CHUNKSIZE 2048#define SECITEMFROMITEM(arena, to, from) \	tmp.data = from.data; tmp.len = from.len; to.type = siBuffer; \	if (SECITEM_CopyItem(arena, &to, &tmp) != SECSuccess) goto loser;#define ITEMFROMSECITEM(to, from) \	to.data = from.data; to.len = from.len;static const B_ALGORITHM_METHOD *rand_chooser[] = {	&AM_SHA_RANDOM,	(B_ALGORITHM_METHOD *)NULL_PTR};static B_ALGORITHM_OBJ generateRandomAlgorithm(int numBytes, unsigned char *seedData){	SECItem seed = { siBuffer, 0, 0 };	B_ALGORITHM_OBJ randomAlgorithm = NULL_PTR;	int status;	/*  Allocate space for random seed.  */	if (seedData) {		seed.len = numBytes;		seed.data = seedData;	} else {		if (SECITEM_AllocItem(NULL, &seed, numBytes) == NULL) {			PORT_SetError(PR_OUT_OF_MEMORY_ERROR);			goto loser;		}		if ((status = RNG_GenerateGlobalRandomBytes(seed.data, seed.len)) 		     != 0) {			PORT_SetError(PR_OUT_OF_MEMORY_ERROR);			goto loser;		}	}	/*  Generate the random seed.  */	if ((status = B_CreateAlgorithmObject(&randomAlgorithm)) != 0) {		PORT_SetError(PR_OUT_OF_MEMORY_ERROR);		goto loser;	}	if ((status = B_SetAlgorithmInfo(randomAlgorithm, AI_SHA1Random, 	                                 NULL_PTR)) != 0) {		PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);		goto loser;	}	if ((status = B_RandomInit(randomAlgorithm, rand_chooser,	                           (A_SURRENDER_CTX *)NULL_PTR)) != 0) {		PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);		goto loser;	}	if ((status = B_RandomUpdate(randomAlgorithm, seed.data, seed.len,	                             (A_SURRENDER_CTX *)NULL_PTR)) != 0) {		PORT_SetError(SEC_ERROR_BAD_DATA);		goto loser;	}	if (seedData == NULL)		SECITEM_FreeItem(&seed, PR_FALSE);	return randomAlgorithm;loser:	if (randomAlgorithm != NULL_PTR)		B_DestroyAlgorithmObject(&randomAlgorithm);	if (seedData == NULL)		SECITEM_FreeItem(&seed, PR_FALSE);	return NULL_PTR;}/******************************************************************************* BLAPI implementation of DES******************************************************************************/struct DESContextStr {    B_ALGORITHM_OBJ     algobj;	B_ALGORITHM_METHOD *alg_chooser[3];	B_KEY_OBJ           keyobj;};DESContext *DES_CreateContext(unsigned char *key, unsigned char *iv,                  int mode, PRBool encrypt){    /* BLAPI */	DESContext *cx;	/* BSAFE */	B_BLK_CIPHER_W_FEEDBACK_PARAMS fbParams;	ITEM                           ivItem;	unsigned int                   blockLength = DES_BLOCK_SIZE;	int status;	cx = (DESContext *)PORT_ZAlloc(sizeof(DESContext));	if (cx == NULL) {		PORT_SetError(PR_OUT_OF_MEMORY_ERROR);		return NULL;	}	/* Create an encryption object. */	cx->algobj = (B_ALGORITHM_OBJ)NULL_PTR;	if ((status = B_CreateAlgorithmObject(&cx->algobj)) != 0) {		PORT_SetError(PR_OUT_OF_MEMORY_ERROR);		goto loser;	}	/* Set the IV. */	ivItem.data = iv;	ivItem.len = DES_BLOCK_SIZE;	/* Create the key. */	cx->keyobj = (B_KEY_OBJ)NULL_PTR;	if ((status = B_CreateKeyObject(&cx->keyobj)) != 0) {		PORT_SetError(PR_OUT_OF_MEMORY_ERROR);		goto loser;	}	/* Set fields common to all DES modes. */	fbParams.encryptionParams     = NULL_PTR;	fbParams.paddingMethodName    = (unsigned char *)"nopad";	fbParams.paddingParams        = NULL_PTR;	/* Set mode-specific fields. */	switch (mode) {	case NSS_DES:		fbParams.encryptionMethodName = (unsigned char *)"des";		fbParams.feedbackMethodName   = (unsigned char *)"ecb";		fbParams.feedbackParams       = (POINTER)&blockLength;		if ((status = B_SetKeyInfo(cx->keyobj, KI_DES8Strong, (POINTER)key)) 		     != 0) {			PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);			goto loser;		}		if (encrypt) {			cx->alg_chooser[0] = &AM_DES_ENCRYPT;			cx->alg_chooser[1] = &AM_ECB_ENCRYPT;		} else {			cx->alg_chooser[0] = &AM_DES_DECRYPT;			cx->alg_chooser[1] = &AM_ECB_DECRYPT;		}		cx->alg_chooser[2] = (B_ALGORITHM_METHOD *)NULL_PTR;		break;	case NSS_DES_CBC:		fbParams.encryptionMethodName = (unsigned char *)"des";		fbParams.feedbackMethodName   = (unsigned char *)"cbc";		fbParams.feedbackParams       = (POINTER)&ivItem;		if ((status = B_SetKeyInfo(cx->keyobj, KI_DES8Strong, (POINTER)key)) 		     != 0) {			PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);			goto loser;		}		if (encrypt) {			cx->alg_chooser[0] = &AM_DES_ENCRYPT;			cx->alg_chooser[1] = &AM_CBC_ENCRYPT;		} else {			cx->alg_chooser[0] = &AM_DES_DECRYPT;			cx->alg_chooser[1] = &AM_CBC_DECRYPT;		}		cx->alg_chooser[2] = (B_ALGORITHM_METHOD *)NULL_PTR;		break;	case NSS_DES_EDE3:		fbParams.encryptionMethodName = (unsigned char *)"des_ede";		fbParams.feedbackMethodName   = (unsigned char *)"ecb";		fbParams.feedbackParams       = (POINTER)&blockLength;		if ((status = B_SetKeyInfo(cx->keyobj, KI_DES24Strong, (POINTER)key)) 		     != 0) {			PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);			goto loser;		}		if (encrypt) {			cx->alg_chooser[0] = &AM_DES_EDE_ENCRYPT;			cx->alg_chooser[1] = &AM_ECB_ENCRYPT;		} else {			cx->alg_chooser[0] = &AM_DES_EDE_DECRYPT;			cx->alg_chooser[1] = &AM_ECB_DECRYPT;		}		cx->alg_chooser[2] = (B_ALGORITHM_METHOD *)NULL_PTR;		break;	case NSS_DES_EDE3_CBC:		fbParams.encryptionMethodName = (unsigned char *)"des_ede";		fbParams.feedbackMethodName   = (unsigned char *)"cbc";		fbParams.feedbackParams       = (POINTER)&ivItem;		if ((status = B_SetKeyInfo(cx->keyobj, KI_DES24Strong, (POINTER)key)) 		     != 0) {			PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);			goto loser;		}		if (encrypt) {			cx->alg_chooser[0] = &AM_DES_EDE_ENCRYPT;			cx->alg_chooser[1] = &AM_CBC_ENCRYPT;		} else {			cx->alg_chooser[0] = &AM_DES_EDE_DECRYPT;			cx->alg_chooser[1] = &AM_CBC_DECRYPT;		}		cx->alg_chooser[2] = (B_ALGORITHM_METHOD *)NULL_PTR;		break;	default:		PORT_SetError(SEC_ERROR_INVALID_ARGS);		goto loser;	}	if ((status = B_SetAlgorithmInfo(cx->algobj, AI_FeedbackCipher,	                                 (POINTER)&fbParams)) != 0) {		PORT_SetError(SEC_ERROR_INVALID_ARGS);		goto loser;	}	return cx;loser:	DES_DestroyContext(cx, PR_TRUE);	return NULL;}void DES_DestroyContext(DESContext *cx, PRBool freeit){	if (freeit) {		PORT_Assert(cx != NULL);		if (cx == NULL) {			PORT_SetError(SEC_ERROR_INVALID_ARGS);			return;		}		if (cx->keyobj != NULL_PTR)			B_DestroyKeyObject(&cx->keyobj);		if (cx->algobj != NULL_PTR)			B_DestroyAlgorithmObject(&cx->algobj);		PORT_ZFree(cx, sizeof(DESContext));	}}SECStatus DES_Encrypt(DESContext *cx, unsigned char *output,            unsigned int *outputLen, unsigned int maxOutputLen,            unsigned char *input, unsigned int inputLen){	unsigned int outputLenUpdate, outputLenFinal;	int status;	PORT_Assert(cx != NULL);	if (cx == NULL) {		PORT_SetError(SEC_ERROR_INVALID_ARGS);		return SECFailure;	}	PORT_Assert((inputLen & (DES_BLOCK_SIZE -1 )) == 0);	if (inputLen & (DES_BLOCK_SIZE -1 )) {		PORT_SetError(SEC_ERROR_INVALID_ARGS);		return SECFailure;	}	PORT_Assert(maxOutputLen >= inputLen); /* check for enough room */	if (maxOutputLen < inputLen) {		PORT_SetError(SEC_ERROR_INVALID_ARGS);		return SECFailure;	}	if ((status = B_EncryptInit(cx->algobj, cx->keyobj, cx->alg_chooser,	                            (A_SURRENDER_CTX *)NULL_PTR)) != 0) {		PORT_SetError(SEC_ERROR_INVALID_ARGS);		return SECFailure;	}	if ((status = B_EncryptUpdate(cx->algobj, 	                              output, 	                              &outputLenUpdate,	                              maxOutputLen, 	                              input, 	                              inputLen,	                              (B_ALGORITHM_OBJ)NULL_PTR,	                              (A_SURRENDER_CTX *)NULL_PTR)) != 0) {		PORT_SetError(SEC_ERROR_BAD_DATA);		return SECFailure;	}	if ((status = B_EncryptFinal(cx->algobj, 	                             output + outputLenUpdate, 	                             &outputLenFinal, 	                             maxOutputLen - outputLenUpdate,	                             (B_ALGORITHM_OBJ)NULL_PTR,	                             (A_SURRENDER_CTX *)NULL_PTR)) != 0) {		PORT_SetError(SEC_ERROR_BAD_DATA);		return SECFailure;	}	*outputLen = outputLenUpdate + outputLenFinal;	return SECSuccess;}SECStatus DES_Decrypt(DESContext *cx, unsigned char *output,            unsigned int *outputLen, unsigned int maxOutputLen,            unsigned char *input, unsigned int inputLen){	unsigned int outputLenUpdate, outputLenFinal;	int status;	ptrdiff_t inpptr;	unsigned char *inp = NULL;	PRBool cpybuffer = PR_FALSE;	/*  The BSAFE Crypto-C 4.1 library with which we tested on a Sun 	 *  UltraSparc crashed when the input to an DES CBC decryption operation	 *  was not 4-byte aligned.	 *  So, we work around this problem by aligning unaligned input in a	 *  temporary buffer.	 */	inpptr = (ptrdiff_t)input;	if (inpptr & 0x03) {		inp = PORT_ZAlloc(inputLen);		if (inp == NULL) {			PORT_SetError(PR_OUT_OF_MEMORY_ERROR);			return SECFailure;		}		PORT_Memcpy(inp, input, inputLen);		cpybuffer = PR_TRUE;	} else {		inp = input;	}	PORT_Assert(cx != NULL);	if (cx == NULL) {		PORT_SetError(SEC_ERROR_INVALID_ARGS);		return SECFailure;	}	PORT_Assert((inputLen & (DES_BLOCK_SIZE - 1)) == 0);

⌨️ 快捷键说明

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