Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Functions
aeskeywrap.c File Reference
#include "prcpucfg.h"
#include "prtypes.h"
#include "secport.h"
#include "secerr.h"
#include "blapi.h"
#include "rijndael.h"

Go to the source code of this file.

Classes

struct  AESKeyWrapContextStr

Defines

#define BIG_ENDIAN_WITH_64_BIT_REGISTERS   1
#define A   B[0]
#define A   B[0]

Functions

AESKeyWrapContext * AESKeyWrap_AllocateContext (void)
SECStatus AESKeyWrap_InitContext (AESKeyWrapContext *cx, const unsigned char *key, unsigned int keylen, const unsigned char *iv, int x1, unsigned int encrypt, unsigned int x2)
AESKeyWrapContext * AESKeyWrap_CreateContext (const unsigned char *key, const unsigned char *iv, int encrypt, unsigned int keylen)
void AESKeyWrap_DestroyContext (AESKeyWrapContext *cx, PRBool freeit)
SECStatus AESKeyWrap_Encrypt (AESKeyWrapContext *cx, unsigned char *output, unsigned int *pOutputLen, unsigned int maxOutputLen, const unsigned char *input, unsigned int inputLen)
SECStatus AESKeyWrap_Decrypt (AESKeyWrapContext *cx, unsigned char *output, unsigned int *pOutputLen, unsigned int maxOutputLen, const unsigned char *input, unsigned int inputLen)

Class Documentation

struct AESKeyWrapContextStr

Definition at line 55 of file aeskeywrap.c.

Class Members
AESContext aescx
unsigned char iv

Define Documentation

#define A   B[0]
#define A   B[0]

Definition at line 47 of file aeskeywrap.c.


Function Documentation

AESKeyWrapContext* AESKeyWrap_AllocateContext ( void  )

Definition at line 66 of file aeskeywrap.c.

{
    AESKeyWrapContext * cx = PORT_New(AESKeyWrapContext);
    return cx;
}

Here is the caller graph for this function:

AESKeyWrapContext* AESKeyWrap_CreateContext ( const unsigned char *  key,
const unsigned char *  iv,
int  encrypt,
unsigned int  keylen 
)

Definition at line 102 of file aeskeywrap.c.

{
    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;
}

Here is the caller graph for this function:

SECStatus AESKeyWrap_Decrypt ( AESKeyWrapContext *  cx,
unsigned char *  output,
unsigned int pOutputLen,
unsigned int  maxOutputLen,
const unsigned char *  input,
unsigned int  inputLen 
)

Definition at line 322 of file aeskeywrap.c.

{
    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;
}

Here is the caller graph for this function:

void AESKeyWrap_DestroyContext ( AESKeyWrapContext *  cx,
PRBool  freeit 
)

Definition at line 123 of file aeskeywrap.c.

{
    if (cx) {
       AES_DestroyContext(&cx->aescx, PR_FALSE);
/*     memset(cx, 0, sizeof *cx); */
       if (freeit)
           PORT_Free(cx);
    }
}

Here is the caller graph for this function:

SECStatus AESKeyWrap_Encrypt ( AESKeyWrapContext *  cx,
unsigned char *  output,
unsigned int pOutputLen,
unsigned int  maxOutputLen,
const unsigned char *  input,
unsigned int  inputLen 
)

Definition at line 226 of file aeskeywrap.c.

{
    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;
}

Here is the caller graph for this function:

SECStatus AESKeyWrap_InitContext ( AESKeyWrapContext *  cx,
const unsigned char *  key,
unsigned int  keylen,
const unsigned char *  iv,
int  x1,
unsigned int  encrypt,
unsigned int  x2 
)

Definition at line 73 of file aeskeywrap.c.

{
    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;
}

Here is the caller graph for this function: