summaryrefslogtreecommitdiff
path: root/nss/lib/freebl/aeskeywrap.c
diff options
context:
space:
mode:
Diffstat (limited to 'nss/lib/freebl/aeskeywrap.c')
-rw-r--r--nss/lib/freebl/aeskeywrap.c358
1 files changed, 182 insertions, 176 deletions
diff --git a/nss/lib/freebl/aeskeywrap.c b/nss/lib/freebl/aeskeywrap.c
index c1c95b3..79ff8a8 100644
--- a/nss/lib/freebl/aeskeywrap.c
+++ b/nss/lib/freebl/aeskeywrap.c
@@ -15,15 +15,15 @@
#else
#define BIG_ENDIAN_WITH_64_BIT_REGISTERS 1
#endif
-#include "prtypes.h" /* for PRUintXX */
-#include "secport.h" /* for PORT_XXX */
+#include "prtypes.h" /* for PRUintXX */
+#include "secport.h" /* for PORT_XXX */
#include "secerr.h"
-#include "blapi.h" /* for AES_ functions */
+#include "blapi.h" /* for AES_ functions */
#include "rijndael.h"
struct AESKeyWrapContextStr {
- unsigned char iv[AES_KEY_WRAP_IV_BYTES];
- AESContext aescx;
+ unsigned char iv[AES_KEY_WRAP_IV_BYTES];
+ AESContext aescx;
};
/******************************************/
@@ -31,71 +31,71 @@ struct AESKeyWrapContextStr {
** AES key wrap algorithm, RFC 3394
*/
-AESKeyWrapContext *
+AESKeyWrapContext *
AESKeyWrap_AllocateContext(void)
{
- AESKeyWrapContext * cx = PORT_New(AESKeyWrapContext);
+ 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
+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;
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
}
if (iv) {
- memcpy(cx->iv, iv, sizeof cx->iv);
+ memcpy(cx->iv, iv, sizeof cx->iv);
} else {
- memset(cx->iv, 0xA6, sizeof cx->iv);
+ memset(cx->iv, 0xA6, sizeof cx->iv);
}
- rv = AES_InitContext(&cx->aescx, key, keylen, NULL, NSS_AES, encrypt,
- AES_BLOCK_SIZE);
+ 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)
+** "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,
+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 */
+ 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 */
+ 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
+** "cx" the context
+** "freeit" if PR_TRUE then free the object as well as its sub-objects
*/
-extern void
+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);
+ AES_DestroyContext(&cx->aescx, PR_FALSE);
+ /* memset(cx, 0, sizeof *cx); */
+ if (freeit)
+ PORT_Free(cx);
}
}
@@ -112,18 +112,18 @@ AESKeyWrap_DestroyContext(AESKeyWrapContext *cx, PRBool freeit)
/* 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];
+ 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];
@@ -136,30 +136,31 @@ increment_and_xor(unsigned char *A, unsigned char *T)
}
/* 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
+** (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)
+xor_and_decrement(PRUint64 *A, PRUint64 *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]--;
+ unsigned char *TP = (unsigned char *)T;
+ const PRUint64 mask = 0xFF;
+ *A = ((*A & mask << 56) ^ (*T & mask << 56)) |
+ ((*A & mask << 48) ^ (*T & mask << 48)) |
+ ((*A & mask << 40) ^ (*T & mask << 40)) |
+ ((*A & mask << 32) ^ (*T & mask << 32)) |
+ ((*A & mask << 24) ^ (*T & mask << 23)) |
+ ((*A & mask << 16) ^ (*T & mask << 16)) |
+ ((*A & mask << 8) ^ (*T & mask << 8)) |
+ ((*A & mask) ^ (*T & mask));
+ if (!TP[7]--)
+ if (!TP[6]--)
+ if (!TP[5]--)
+ if (!TP[4]--)
+ if (!TP[3]--)
+ if (!TP[2]--)
+ if (!TP[1]--)
+ TP[0]--;
}
/* Given an unsigned long t (in host byte order), store this value as a
@@ -168,13 +169,20 @@ xor_and_decrement(unsigned char *A, unsigned char *T)
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[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;
}
@@ -182,56 +190,56 @@ set_t(unsigned char *pt, unsigned long t)
/*
** 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
+** "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
+extern SECStatus
AESKeyWrap_Encrypt(AESKeyWrapContext *cx, unsigned char *output,
- unsigned int *pOutputLen, unsigned int maxOutputLen,
- const unsigned char *input, unsigned int inputLen)
+ 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;
+ 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];
+ 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;
+ PORT_SetError(SEC_ERROR_INPUT_LEN);
+ return s;
}
#ifdef maybe
- if (!output && pOutputLen) { /* caller is asking for output size */
- *pOutputLen = outLen;
- return SECSuccess;
+ 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;
+ PORT_SetError(SEC_ERROR_OUTPUT_LEN);
+ return s;
}
if (cx == NULL || output == NULL || input == NULL) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return s;
+ 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. */
- /*
+ return s; /* error is already set. */
+ /*
** 1) Initialize variables.
*/
memcpy(&A, cx->iv, AES_KEY_WRAP_IV_BYTES);
@@ -241,35 +249,35 @@ AESKeyWrap_Encrypt(AESKeyWrapContext *cx, unsigned char *output,
#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); */
+ 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;
+ A ^= ++t;
#else
- increment_and_xor((unsigned char *)&A, (unsigned char *)&t);
+ 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;
+ R[0] = A;
+ memcpy(output, &R[0], outLen);
+ if (pOutputLen)
+ *pOutputLen = outLen;
} else if (pOutputLen) {
- *pOutputLen = 0;
+ *pOutputLen = 0;
}
PORT_ZFree(R, outLen);
return s;
@@ -278,104 +286,102 @@ AESKeyWrap_Encrypt(AESKeyWrapContext *cx, unsigned char *output,
/*
** 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
+** "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
+extern SECStatus
AESKeyWrap_Decrypt(AESKeyWrapContext *cx, unsigned char *output,
- unsigned int *pOutputLen, unsigned int maxOutputLen,
- const unsigned char *input, unsigned int inputLen)
+ 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;
+ 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]
+ PRUint64 t;
+ PRUint64 B[2];
/* Check args */
- if (inputLen < 3 * AES_KEY_WRAP_BLOCK_SIZE ||
+ if (inputLen < 3 * AES_KEY_WRAP_BLOCK_SIZE ||
0 != inputLen % AES_KEY_WRAP_BLOCK_SIZE) {
- PORT_SetError(SEC_ERROR_INPUT_LEN);
- return s;
+ 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;
+ 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;
+ PORT_SetError(SEC_ERROR_OUTPUT_LEN);
+ return s;
}
if (cx == NULL || output == NULL || input == NULL) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return s;
+ 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. */
+ return s; /* error is already set. */
nBlocks--;
- /*
+ /*
** 1) Initialize variables.
*/
memcpy(&R[0], input, inputLen);
- A = R[0];
+ B[0] = 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; */
+ 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--;
+ B[0] ^= t--;
#else
- xor_and_decrement((unsigned char *)&A, (unsigned char *)&t);
+ xor_and_decrement(&B[0], &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];
- }
+ 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;
- }
+ int bad = memcmp(&B[0], 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;
+ *pOutputLen = 0;
}
PORT_ZFree(R, inputLen);
return s;