summaryrefslogtreecommitdiff
path: root/security/nss/lib/freebl/aeskeywrap.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/freebl/aeskeywrap.c')
-rw-r--r--security/nss/lib/freebl/aeskeywrap.c417
1 files changed, 0 insertions, 417 deletions
diff --git a/security/nss/lib/freebl/aeskeywrap.c b/security/nss/lib/freebl/aeskeywrap.c
deleted file mode 100644
index 1fd8b5155..000000000
--- a/security/nss/lib/freebl/aeskeywrap.c
+++ /dev/null
@@ -1,417 +0,0 @@
-/*
- * aeskeywrap.c - implement AES Key Wrap algorithm from RFC 3394
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * 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 the Initial Developer are Copyright (C) 2002
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-/* $Id$ */
-
-/* $Id$ */
-
-#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 {
- PORT_SetError(SEC_ERROR_BAD_DATA);
- if (pOutputLen)
- *pOutputLen = 0;
- }
- } else if (pOutputLen) {
- *pOutputLen = 0;
- }
- PORT_ZFree(R, inputLen);
- return s;
-}
-#undef A