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 + -
显示快捷键?