| Index: nss/lib/freebl/aeskeywrap.c
|
| diff --git a/nss/lib/freebl/aeskeywrap.c b/nss/lib/freebl/aeskeywrap.c
|
| deleted file mode 100644
|
| index c1c95b3515849ce66f1fdfb2047979460a91c001..0000000000000000000000000000000000000000
|
| --- a/nss/lib/freebl/aeskeywrap.c
|
| +++ /dev/null
|
| @@ -1,383 +0,0 @@
|
| -/*
|
| - * aeskeywrap.c - implement AES Key Wrap algorithm from RFC 3394
|
| - *
|
| - * This Source Code Form is subject to the terms of the Mozilla Public
|
| - * License, v. 2.0. If a copy of the MPL was not distributed with this
|
| - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
| -
|
| -#ifdef FREEBL_NO_DEPEND
|
| -#include "stubs.h"
|
| -#endif
|
| -
|
| -#include "prcpucfg.h"
|
| -#if defined(IS_LITTLE_ENDIAN) || defined(SHA_NO_LONG_LONG)
|
| -#define BIG_ENDIAN_WITH_64_BIT_REGISTERS 0
|
| -#else
|
| -#define BIG_ENDIAN_WITH_64_BIT_REGISTERS 1
|
| -#endif
|
| -#include "prtypes.h" /* for PRUintXX */
|
| -#include "secport.h" /* for PORT_XXX */
|
| -#include "secerr.h"
|
| -#include "blapi.h" /* for AES_ functions */
|
| -#include "rijndael.h"
|
| -
|
| -struct AESKeyWrapContextStr {
|
| - unsigned char iv[AES_KEY_WRAP_IV_BYTES];
|
| - AESContext aescx;
|
| -};
|
| -
|
| -/******************************************/
|
| -/*
|
| -** AES key wrap algorithm, RFC 3394
|
| -*/
|
| -
|
| -AESKeyWrapContext *
|
| -AESKeyWrap_AllocateContext(void)
|
| -{
|
| - AESKeyWrapContext * cx = PORT_New(AESKeyWrapContext);
|
| - return cx;
|
| -}
|
| -
|
| -SECStatus
|
| -AESKeyWrap_InitContext(AESKeyWrapContext *cx,
|
| - const unsigned char *key,
|
| - unsigned int keylen,
|
| - const unsigned char *iv,
|
| - int x1,
|
| - unsigned int encrypt,
|
| - unsigned int x2)
|
| -{
|
| - SECStatus rv = SECFailure;
|
| - if (!cx) {
|
| - PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
| - return SECFailure;
|
| - }
|
| - if (iv) {
|
| - memcpy(cx->iv, iv, sizeof cx->iv);
|
| - } else {
|
| - memset(cx->iv, 0xA6, sizeof cx->iv);
|
| - }
|
| - rv = AES_InitContext(&cx->aescx, key, keylen, NULL, NSS_AES, encrypt,
|
| - AES_BLOCK_SIZE);
|
| - return rv;
|
| -}
|
| -
|
| -/*
|
| -** Create a new AES context suitable for AES encryption/decryption.
|
| -** "key" raw key data
|
| -** "keylen" the number of bytes of key data (16, 24, or 32)
|
| -*/
|
| -extern AESKeyWrapContext *
|
| -AESKeyWrap_CreateContext(const unsigned char *key, const unsigned char *iv,
|
| - int encrypt, unsigned int keylen)
|
| -{
|
| - SECStatus rv;
|
| - AESKeyWrapContext * cx = AESKeyWrap_AllocateContext();
|
| - if (!cx)
|
| - return NULL; /* error is already set */
|
| - rv = AESKeyWrap_InitContext(cx, key, keylen, iv, 0, encrypt, 0);
|
| - if (rv != SECSuccess) {
|
| - PORT_Free(cx);
|
| - cx = NULL; /* error should already be set */
|
| - }
|
| - return cx;
|
| -}
|
| -
|
| -/*
|
| -** Destroy a AES KeyWrap context.
|
| -** "cx" the context
|
| -** "freeit" if PR_TRUE then free the object as well as its sub-objects
|
| -*/
|
| -extern void
|
| -AESKeyWrap_DestroyContext(AESKeyWrapContext *cx, PRBool freeit)
|
| -{
|
| - if (cx) {
|
| - AES_DestroyContext(&cx->aescx, PR_FALSE);
|
| -/* memset(cx, 0, sizeof *cx); */
|
| - if (freeit)
|
| - PORT_Free(cx);
|
| - }
|
| -}
|
| -
|
| -#if !BIG_ENDIAN_WITH_64_BIT_REGISTERS
|
| -
|
| -/* The AES Key Wrap algorithm has 64-bit values that are ALWAYS big-endian
|
| -** (Most significant byte first) in memory. The only ALU operations done
|
| -** on them are increment, decrement, and XOR. So, on little-endian CPUs,
|
| -** and on CPUs that lack 64-bit registers, these big-endian 64-bit operations
|
| -** are simulated in the following code. This is thought to be faster and
|
| -** simpler than trying to convert the data to little-endian and back.
|
| -*/
|
| -
|
| -/* A and T point to two 64-bit values stored most signficant byte first
|
| -** (big endian). This function increments the 64-bit value T, and then
|
| -** XORs it with A, changing A.
|
| -*/
|
| -static void
|
| -increment_and_xor(unsigned char *A, unsigned char *T)
|
| -{
|
| - if (!++T[7])
|
| - if (!++T[6])
|
| - if (!++T[5])
|
| - if (!++T[4])
|
| - if (!++T[3])
|
| - if (!++T[2])
|
| - if (!++T[1])
|
| - ++T[0];
|
| -
|
| - A[0] ^= T[0];
|
| - A[1] ^= T[1];
|
| - A[2] ^= T[2];
|
| - A[3] ^= T[3];
|
| - A[4] ^= T[4];
|
| - A[5] ^= T[5];
|
| - A[6] ^= T[6];
|
| - A[7] ^= T[7];
|
| -}
|
| -
|
| -/* A and T point to two 64-bit values stored most signficant byte first
|
| -** (big endian). This function XORs T with A, giving a new A, then
|
| -** decrements the 64-bit value T.
|
| -*/
|
| -static void
|
| -xor_and_decrement(unsigned char *A, unsigned char *T)
|
| -{
|
| - A[0] ^= T[0];
|
| - A[1] ^= T[1];
|
| - A[2] ^= T[2];
|
| - A[3] ^= T[3];
|
| - A[4] ^= T[4];
|
| - A[5] ^= T[5];
|
| - A[6] ^= T[6];
|
| - A[7] ^= T[7];
|
| -
|
| - if (!T[7]--)
|
| - if (!T[6]--)
|
| - if (!T[5]--)
|
| - if (!T[4]--)
|
| - if (!T[3]--)
|
| - if (!T[2]--)
|
| - if (!T[1]--)
|
| - T[0]--;
|
| -
|
| -}
|
| -
|
| -/* Given an unsigned long t (in host byte order), store this value as a
|
| -** 64-bit big-endian value (MSB first) in *pt.
|
| -*/
|
| -static void
|
| -set_t(unsigned char *pt, unsigned long t)
|
| -{
|
| - pt[7] = (unsigned char)t; t >>= 8;
|
| - pt[6] = (unsigned char)t; t >>= 8;
|
| - pt[5] = (unsigned char)t; t >>= 8;
|
| - pt[4] = (unsigned char)t; t >>= 8;
|
| - pt[3] = (unsigned char)t; t >>= 8;
|
| - pt[2] = (unsigned char)t; t >>= 8;
|
| - pt[1] = (unsigned char)t; t >>= 8;
|
| - pt[0] = (unsigned char)t;
|
| -}
|
| -
|
| -#endif
|
| -
|
| -/*
|
| -** Perform AES key wrap.
|
| -** "cx" the context
|
| -** "output" the output buffer to store the encrypted data.
|
| -** "outputLen" how much data is stored in "output". Set by the routine
|
| -** after some data is stored in output.
|
| -** "maxOutputLen" the maximum amount of data that can ever be
|
| -** stored in "output"
|
| -** "input" the input data
|
| -** "inputLen" the amount of input data
|
| -*/
|
| -extern SECStatus
|
| -AESKeyWrap_Encrypt(AESKeyWrapContext *cx, unsigned char *output,
|
| - unsigned int *pOutputLen, unsigned int maxOutputLen,
|
| - const unsigned char *input, unsigned int inputLen)
|
| -{
|
| - PRUint64 * R = NULL;
|
| - unsigned int nBlocks;
|
| - unsigned int i, j;
|
| - unsigned int aesLen = AES_BLOCK_SIZE;
|
| - unsigned int outLen = inputLen + AES_KEY_WRAP_BLOCK_SIZE;
|
| - SECStatus s = SECFailure;
|
| - /* These PRUint64s are ALWAYS big endian, regardless of CPU orientation. */
|
| - PRUint64 t;
|
| - PRUint64 B[2];
|
| -
|
| -#define A B[0]
|
| -
|
| - /* Check args */
|
| - if (!inputLen || 0 != inputLen % AES_KEY_WRAP_BLOCK_SIZE) {
|
| - PORT_SetError(SEC_ERROR_INPUT_LEN);
|
| - return s;
|
| - }
|
| -#ifdef maybe
|
| - if (!output && pOutputLen) { /* caller is asking for output size */
|
| - *pOutputLen = outLen;
|
| - return SECSuccess;
|
| - }
|
| -#endif
|
| - if (maxOutputLen < outLen) {
|
| - PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
| - return s;
|
| - }
|
| - if (cx == NULL || output == NULL || input == NULL) {
|
| - PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
| - return s;
|
| - }
|
| - nBlocks = inputLen / AES_KEY_WRAP_BLOCK_SIZE;
|
| - R = PORT_NewArray(PRUint64, nBlocks + 1);
|
| - if (!R)
|
| - return s; /* error is already set. */
|
| - /*
|
| - ** 1) Initialize variables.
|
| - */
|
| - memcpy(&A, cx->iv, AES_KEY_WRAP_IV_BYTES);
|
| - memcpy(&R[1], input, inputLen);
|
| -#if BIG_ENDIAN_WITH_64_BIT_REGISTERS
|
| - t = 0;
|
| -#else
|
| - memset(&t, 0, sizeof t);
|
| -#endif
|
| - /*
|
| - ** 2) Calculate intermediate values.
|
| - */
|
| - for (j = 0; j < 6; ++j) {
|
| - for (i = 1; i <= nBlocks; ++i) {
|
| - B[1] = R[i];
|
| - s = AES_Encrypt(&cx->aescx, (unsigned char *)B, &aesLen,
|
| - sizeof B, (unsigned char *)B, sizeof B);
|
| - if (s != SECSuccess)
|
| - break;
|
| - R[i] = B[1];
|
| - /* here, increment t and XOR A with t (in big endian order); */
|
| -#if BIG_ENDIAN_WITH_64_BIT_REGISTERS
|
| - A ^= ++t;
|
| -#else
|
| - increment_and_xor((unsigned char *)&A, (unsigned char *)&t);
|
| -#endif
|
| - }
|
| - }
|
| - /*
|
| - ** 3) Output the results.
|
| - */
|
| - if (s == SECSuccess) {
|
| - R[0] = A;
|
| - memcpy(output, &R[0], outLen);
|
| - if (pOutputLen)
|
| - *pOutputLen = outLen;
|
| - } else if (pOutputLen) {
|
| - *pOutputLen = 0;
|
| - }
|
| - PORT_ZFree(R, outLen);
|
| - return s;
|
| -}
|
| -#undef A
|
| -
|
| -/*
|
| -** Perform AES key unwrap.
|
| -** "cx" the context
|
| -** "output" the output buffer to store the decrypted data.
|
| -** "outputLen" how much data is stored in "output". Set by the routine
|
| -** after some data is stored in output.
|
| -** "maxOutputLen" the maximum amount of data that can ever be
|
| -** stored in "output"
|
| -** "input" the input data
|
| -** "inputLen" the amount of input data
|
| -*/
|
| -extern SECStatus
|
| -AESKeyWrap_Decrypt(AESKeyWrapContext *cx, unsigned char *output,
|
| - unsigned int *pOutputLen, unsigned int maxOutputLen,
|
| - const unsigned char *input, unsigned int inputLen)
|
| -{
|
| - PRUint64 * R = NULL;
|
| - unsigned int nBlocks;
|
| - unsigned int i, j;
|
| - unsigned int aesLen = AES_BLOCK_SIZE;
|
| - unsigned int outLen;
|
| - SECStatus s = SECFailure;
|
| - /* These PRUint64s are ALWAYS big endian, regardless of CPU orientation. */
|
| - PRUint64 t;
|
| - PRUint64 B[2];
|
| -
|
| -#define A B[0]
|
| -
|
| - /* Check args */
|
| - if (inputLen < 3 * AES_KEY_WRAP_BLOCK_SIZE ||
|
| - 0 != inputLen % AES_KEY_WRAP_BLOCK_SIZE) {
|
| - PORT_SetError(SEC_ERROR_INPUT_LEN);
|
| - return s;
|
| - }
|
| - outLen = inputLen - AES_KEY_WRAP_BLOCK_SIZE;
|
| -#ifdef maybe
|
| - if (!output && pOutputLen) { /* caller is asking for output size */
|
| - *pOutputLen = outLen;
|
| - return SECSuccess;
|
| - }
|
| -#endif
|
| - if (maxOutputLen < outLen) {
|
| - PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
| - return s;
|
| - }
|
| - if (cx == NULL || output == NULL || input == NULL) {
|
| - PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
| - return s;
|
| - }
|
| - nBlocks = inputLen / AES_KEY_WRAP_BLOCK_SIZE;
|
| - R = PORT_NewArray(PRUint64, nBlocks);
|
| - if (!R)
|
| - return s; /* error is already set. */
|
| - nBlocks--;
|
| - /*
|
| - ** 1) Initialize variables.
|
| - */
|
| - memcpy(&R[0], input, inputLen);
|
| - A = R[0];
|
| -#if BIG_ENDIAN_WITH_64_BIT_REGISTERS
|
| - t = 6UL * nBlocks;
|
| -#else
|
| - set_t((unsigned char *)&t, 6UL * nBlocks);
|
| -#endif
|
| - /*
|
| - ** 2) Calculate intermediate values.
|
| - */
|
| - for (j = 0; j < 6; ++j) {
|
| - for (i = nBlocks; i; --i) {
|
| - /* here, XOR A with t (in big endian order) and decrement t; */
|
| -#if BIG_ENDIAN_WITH_64_BIT_REGISTERS
|
| - A ^= t--;
|
| -#else
|
| - xor_and_decrement((unsigned char *)&A, (unsigned char *)&t);
|
| -#endif
|
| - B[1] = R[i];
|
| - s = AES_Decrypt(&cx->aescx, (unsigned char *)B, &aesLen,
|
| - sizeof B, (unsigned char *)B, sizeof B);
|
| - if (s != SECSuccess)
|
| - break;
|
| - R[i] = B[1];
|
| - }
|
| - }
|
| - /*
|
| - ** 3) Output the results.
|
| - */
|
| - if (s == SECSuccess) {
|
| - int bad = memcmp(&A, cx->iv, AES_KEY_WRAP_IV_BYTES);
|
| - if (!bad) {
|
| - memcpy(output, &R[1], outLen);
|
| - if (pOutputLen)
|
| - *pOutputLen = outLen;
|
| - } else {
|
| - s = SECFailure;
|
| - PORT_SetError(SEC_ERROR_BAD_DATA);
|
| - if (pOutputLen)
|
| - *pOutputLen = 0;
|
| - }
|
| - } else if (pOutputLen) {
|
| - *pOutputLen = 0;
|
| - }
|
| - PORT_ZFree(R, inputLen);
|
| - return s;
|
| -}
|
| -#undef A
|
|
|