summaryrefslogtreecommitdiff
path: root/src/nss/kw_aes.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nss/kw_aes.c')
-rw-r--r--src/nss/kw_aes.c1116
1 files changed, 646 insertions, 470 deletions
diff --git a/src/nss/kw_aes.c b/src/nss/kw_aes.c
index 0438e306..0c3a5708 100644
--- a/src/nss/kw_aes.c
+++ b/src/nss/kw_aes.c
@@ -1,14 +1,13 @@
-/**
+/**
*
* XMLSec library
- *
+ *
* AES Algorithm support
- *
+ *
* This is free software; see Copyright file in the source
* distribution for preciese wording.
- *
+ *
* Copyright (c) 2003 America Online, Inc. All rights reserved.
- * Copyright (C) 2010 Aleksey Sanin, All rights reserved.
*/
#ifndef XMLSEC_NO_AES
@@ -29,328 +28,271 @@
#include <xmlsec/nss/crypto.h>
-#include "../kw_aes_des.h"
-
-/*
- * NSS needs to implement AES KW internally and then the code
- * needs to change to use the direct implementation instead.
- *
- * Follow the NSS bug system for more details on the fix
- * http://bugzilla.mozilla.org/show_bug.cgi?id=213795
- */
-/*********************************************************************
- *
- * AES KW implementation
- *
- *********************************************************************/
-static int xmlSecNSSKWAesBlockEncrypt (const xmlSecByte * in,
- xmlSecSize inSize,
- xmlSecByte * out,
- xmlSecSize outSize,
- void * context);
-static int xmlSecNSSKWAesBlockDecrypt (const xmlSecByte * in,
- xmlSecSize inSize,
- xmlSecByte * out,
- xmlSecSize outSize,
- void * context);
-static xmlSecKWAesKlass xmlSecNssKWAesKlass = {
- /* callbacks */
- xmlSecNSSKWAesBlockEncrypt, /* xmlSecKWAesBlockEncryptMethod encrypt; */
- xmlSecNSSKWAesBlockDecrypt, /* xmlSecKWAesBlockDecryptMethod decrypt; */
-
- /* for the future */
- NULL, /* void* reserved0; */
- NULL /* void* reserved1; */
-};
-
-
-
-
-static PK11SymKey* xmlSecNssMakeAesKey (const xmlSecByte *key,
- xmlSecSize keySize,
- int enc);
-static int xmlSecNssAesOp (PK11SymKey *aeskey,
- const xmlSecByte *in,
- xmlSecByte *out,
- int enc);
+#define XMLSEC_NSS_AES128_KEY_SIZE 16
+#define XMLSEC_NSS_AES192_KEY_SIZE 24
+#define XMLSEC_NSS_AES256_KEY_SIZE 32
+#define XMLSEC_NSS_AES_IV_SIZE 16
+#define XMLSEC_NSS_AES_BLOCK_SIZE 16
+#ifndef NSS_AES_KEYWRAP_BUG_FIXED
+static PK11SymKey* xmlSecNssMakeAesKey(const xmlSecByte *key,
+ xmlSecSize keySize, int enc);
+static void xmlSecNssAesOp(PK11SymKey *aeskey,
+ const xmlSecByte *in, xmlSecByte *out,
+ int enc);
+#endif /* NSS_AES_KEYWRAP_BUG_FIXED */
/*********************************************************************
*
* AES KW transforms
*
+ * key (xmlSecBuffer) is located after xmlSecTransform structure
+ *
********************************************************************/
-typedef struct _xmlSecNssKWAesCtx xmlSecNssKWAesCtx,
- *xmlSecNssKWAesCtxPtr;
-struct _xmlSecNssKWAesCtx {
- xmlSecBuffer keyBuffer;
- xmlSecSize keyExpectedSize;
+#define xmlSecNssKWAesGetKey(transform) \
+ ((xmlSecBufferPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+#define xmlSecNssKWAesSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecBuffer))
+
+static int xmlSecNssKWAesInitialize (xmlSecTransformPtr transform);
+static void xmlSecNssKWAesFinalize (xmlSecTransformPtr transform);
+static int xmlSecNssKWAesSetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecNssKWAesSetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecNssKWAesExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+static xmlSecSize xmlSecNssKWAesGetKeySize (xmlSecTransformPtr transform);
+static int xmlSecNssKWAesOp (const xmlSecByte *key,
+ xmlSecSize keySize,
+ const xmlSecByte* in,
+ xmlSecSize inSize,
+ xmlSecByte* out,
+ xmlSecSize outSize,
+ int enc);
+
+static xmlSecTransformKlass xmlSecNssKWAes128Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssKWAesSize, /* xmlSecSize objSize */
+
+ xmlSecNameKWAes128, /* const xmlChar* name; */
+ xmlSecHrefKWAes128, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecNssKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecNssKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssKWAesExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+static xmlSecTransformKlass xmlSecNssKWAes192Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssKWAesSize, /* xmlSecSize objSize */
+
+ xmlSecNameKWAes192, /* const xmlChar* name; */
+ xmlSecHrefKWAes192, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecNssKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecNssKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssKWAesExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+static xmlSecTransformKlass xmlSecNssKWAes256Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecNssKWAesSize, /* xmlSecSize objSize */
+
+ xmlSecNameKWAes256, /* const xmlChar* name; */
+ xmlSecHrefKWAes256, /* const xmlChar* href; */
+ xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
+
+ xmlSecNssKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecNssKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecNssKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
+ xmlSecNssKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ NULL, /* xmlSecTransformValidateMethod validate; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecNssKWAesExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
};
-#define xmlSecNssKWAesSize \
- (sizeof(xmlSecTransform) + sizeof(xmlSecNssKWAesCtx))
-#define xmlSecNssKWAesGetCtx(transform) \
- ((xmlSecNssKWAesCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+#define XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE 8
#define xmlSecNssKWAesCheckId(transform) \
(xmlSecTransformCheckId((transform), xmlSecNssTransformKWAes128Id) || \
xmlSecTransformCheckId((transform), xmlSecNssTransformKWAes192Id) || \
xmlSecTransformCheckId((transform), xmlSecNssTransformKWAes256Id))
-
-static int xmlSecNssKWAesInitialize (xmlSecTransformPtr transform);
-static void xmlSecNssKWAesFinalize (xmlSecTransformPtr transform);
-static int xmlSecNssKWAesSetKeyReq (xmlSecTransformPtr transform,
- xmlSecKeyReqPtr keyReq);
-static int xmlSecNssKWAesSetKey (xmlSecTransformPtr transform,
- xmlSecKeyPtr key);
-static int xmlSecNssKWAesExecute (xmlSecTransformPtr transform,
- int last,
- xmlSecTransformCtxPtr transformCtx);
-
-static xmlSecTransformKlass xmlSecNssKWAes128Klass = {
- /* klass/object sizes */
- sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
- xmlSecNssKWAesSize, /* xmlSecSize objSize */
-
- xmlSecNameKWAes128, /* const xmlChar* name; */
- xmlSecHrefKWAes128, /* const xmlChar* href; */
- xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
-
- xmlSecNssKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */
- xmlSecNssKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */
- NULL, /* xmlSecTransformNodeReadMethod readNode; */
- NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
- xmlSecNssKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
- xmlSecNssKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */
- NULL, /* xmlSecTransformValidateMethod validate; */
- xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
- xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
- xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
- NULL, /* xmlSecTransformPushXmlMethod pushXml; */
- NULL, /* xmlSecTransformPopXmlMethod popXml; */
- xmlSecNssKWAesExecute, /* xmlSecTransformExecuteMethod execute; */
-
- NULL, /* void* reserved0; */
- NULL, /* void* reserved1; */
-};
-
-/**
+/**
* xmlSecNssTransformKWAes128GetKlass:
*
* The AES-128 key wrapper transform klass.
*
* Returns: AES-128 key wrapper transform klass.
*/
-xmlSecTransformId
+xmlSecTransformId
xmlSecNssTransformKWAes128GetKlass(void) {
return(&xmlSecNssKWAes128Klass);
}
-static xmlSecTransformKlass xmlSecNssKWAes192Klass = {
- /* klass/object sizes */
- sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
- xmlSecNssKWAesSize, /* xmlSecSize objSize */
-
- xmlSecNameKWAes192, /* const xmlChar* name; */
- xmlSecHrefKWAes192, /* const xmlChar* href; */
- xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
-
- xmlSecNssKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */
- xmlSecNssKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */
- NULL, /* xmlSecTransformNodeReadMethod readNode; */
- NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
- xmlSecNssKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
- xmlSecNssKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */
- NULL, /* xmlSecTransformValidateMethod validate; */
- xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
- xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
- xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
- NULL, /* xmlSecTransformPushXmlMethod pushXml; */
- NULL, /* xmlSecTransformPopXmlMethod popXml; */
- xmlSecNssKWAesExecute, /* xmlSecTransformExecuteMethod execute; */
-
- NULL, /* void* reserved0; */
- NULL, /* void* reserved1; */
-};
-
-/**
+/**
* xmlSecNssTransformKWAes192GetKlass:
*
* The AES-192 key wrapper transform klass.
*
* Returns: AES-192 key wrapper transform klass.
*/
-xmlSecTransformId
+xmlSecTransformId
xmlSecNssTransformKWAes192GetKlass(void) {
return(&xmlSecNssKWAes192Klass);
}
-static xmlSecTransformKlass xmlSecNssKWAes256Klass = {
- /* klass/object sizes */
- sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
- xmlSecNssKWAesSize, /* xmlSecSize objSize */
-
- xmlSecNameKWAes256, /* const xmlChar* name; */
- xmlSecHrefKWAes256, /* const xmlChar* href; */
- xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
-
- xmlSecNssKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */
- xmlSecNssKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */
- NULL, /* xmlSecTransformNodeReadMethod readNode; */
- NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
- xmlSecNssKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
- xmlSecNssKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */
- NULL, /* xmlSecTransformValidateMethod validate; */
- xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
- xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
- xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
- NULL, /* xmlSecTransformPushXmlMethod pushXml; */
- NULL, /* xmlSecTransformPopXmlMethod popXml; */
- xmlSecNssKWAesExecute, /* xmlSecTransformExecuteMethod execute; */
-
- NULL, /* void* reserved0; */
- NULL, /* void* reserved1; */
-};
-
-/**
+/**
* xmlSecNssTransformKWAes256GetKlass:
*
* The AES-256 key wrapper transform klass.
*
* Returns: AES-256 key wrapper transform klass.
*/
-xmlSecTransformId
+xmlSecTransformId
xmlSecNssTransformKWAes256GetKlass(void) {
return(&xmlSecNssKWAes256Klass);
}
-static int
+static int
xmlSecNssKWAesInitialize(xmlSecTransformPtr transform) {
- xmlSecNssKWAesCtxPtr ctx;
int ret;
-
+
xmlSecAssert2(xmlSecNssKWAesCheckId(transform), -1);
xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWAesSize), -1);
-
- ctx = xmlSecNssKWAesGetCtx(transform);
- xmlSecAssert2(ctx != NULL, -1);
-
- if(xmlSecTransformCheckId(transform, xmlSecNssTransformKWAes128Id)) {
- ctx->keyExpectedSize = XMLSEC_KW_AES128_KEY_SIZE;
- } else if(xmlSecTransformCheckId(transform, xmlSecNssTransformKWAes192Id)) {
- ctx->keyExpectedSize = XMLSEC_KW_AES192_KEY_SIZE;
- } else if(xmlSecTransformCheckId(transform, xmlSecNssTransformKWAes256Id)) {
- ctx->keyExpectedSize = XMLSEC_KW_AES256_KEY_SIZE;
- } else {
- xmlSecError(XMLSEC_ERRORS_HERE,
- xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
- NULL,
- XMLSEC_ERRORS_R_INVALID_TRANSFORM,
- XMLSEC_ERRORS_NO_MESSAGE);
- return(-1);
- }
-
- ret = xmlSecBufferInitialize(&(ctx->keyBuffer), 0);
+
+ ret = xmlSecBufferInitialize(xmlSecNssKWAesGetKey(transform), 0);
if(ret < 0) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
- "xmlSecBufferInitialize",
- XMLSEC_ERRORS_R_XMLSEC_FAILED,
- XMLSEC_ERRORS_NO_MESSAGE);
- return(-1);
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferInitialize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
}
-
+
return(0);
}
-static void
+static void
xmlSecNssKWAesFinalize(xmlSecTransformPtr transform) {
- xmlSecNssKWAesCtxPtr ctx;
-
xmlSecAssert(xmlSecNssKWAesCheckId(transform));
xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecNssKWAesSize));
-
- ctx = xmlSecNssKWAesGetCtx(transform);
- xmlSecAssert(ctx != NULL);
-
- xmlSecBufferFinalize(&(ctx->keyBuffer));
+
+ if(xmlSecNssKWAesGetKey(transform) != NULL) {
+ xmlSecBufferFinalize(xmlSecNssKWAesGetKey(transform));
+ }
}
-static int
+static int
xmlSecNssKWAesSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
- xmlSecNssKWAesCtxPtr ctx;
-
xmlSecAssert2(xmlSecNssKWAesCheckId(transform), -1);
xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWAesSize), -1);
xmlSecAssert2(keyReq != NULL, -1);
- ctx = xmlSecNssKWAesGetCtx(transform);
- xmlSecAssert2(ctx != NULL, -1);
-
- keyReq->keyId = xmlSecNssKeyDataAesId;
+ keyReq->keyId = xmlSecNssKeyDataAesId;
keyReq->keyType = xmlSecKeyDataTypeSymmetric;
if(transform->operation == xmlSecTransformOperationEncrypt) {
- keyReq->keyUsage = xmlSecKeyUsageEncrypt;
+ keyReq->keyUsage = xmlSecKeyUsageEncrypt;
} else {
- keyReq->keyUsage = xmlSecKeyUsageDecrypt;
+ keyReq->keyUsage = xmlSecKeyUsageDecrypt;
}
- keyReq->keyBitsSize = 8 * ctx->keyExpectedSize;
-
+ keyReq->keyBitsSize = 8 * xmlSecNssKWAesGetKeySize(transform);
+
return(0);
}
-static int
+static int
xmlSecNssKWAesSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
- xmlSecNssKWAesCtxPtr ctx;
xmlSecBufferPtr buffer;
xmlSecSize keySize;
+ xmlSecSize expectedKeySize;
int ret;
-
+
xmlSecAssert2(xmlSecNssKWAesCheckId(transform), -1);
xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWAesSize), -1);
+ xmlSecAssert2(xmlSecNssKWAesGetKey(transform) != NULL, -1);
xmlSecAssert2(key != NULL, -1);
xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecNssKeyDataAesId), -1);
-
- ctx = xmlSecNssKWAesGetCtx(transform);
- xmlSecAssert2(ctx != NULL, -1);
-
+
buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key));
xmlSecAssert2(buffer != NULL, -1);
keySize = xmlSecBufferGetSize(buffer);
- if(keySize < ctx->keyExpectedSize) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
- NULL,
- XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,
- "key=%d;expected=%d",
- keySize, ctx->keyExpectedSize);
- return(-1);
+ expectedKeySize = xmlSecNssKWAesGetKeySize(transform);
+ if(keySize < expectedKeySize) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,
+ "key=%d;expected=%d",
+ keySize, expectedKeySize);
+ return(-1);
}
-
- ret = xmlSecBufferSetData(&(ctx->keyBuffer),
- xmlSecBufferGetData(buffer),
- ctx->keyExpectedSize);
+
+ ret = xmlSecBufferSetData(xmlSecNssKWAesGetKey(transform),
+ xmlSecBufferGetData(buffer),
+ expectedKeySize);
if(ret < 0) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
- "xmlSecBufferSetData",
- XMLSEC_ERRORS_R_XMLSEC_FAILED,
- "expected-size=%d",
- ctx->keyExpectedSize);
- return(-1);
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetData",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "expected-size=%d", expectedKeySize);
+ return(-1);
}
return(0);
}
-static int
+static int
xmlSecNssKWAesExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
- xmlSecNssKWAesCtxPtr ctx;
- xmlSecBufferPtr in, out;
- xmlSecSize inSize, outSize, keySize;
+ xmlSecBufferPtr in, out, key;
+ xmlSecSize inSize, outSize, keySize, expectedKeySize;
int ret;
xmlSecAssert2(xmlSecNssKWAesCheckId(transform), -1);
@@ -358,205 +300,317 @@ xmlSecNssKWAesExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtx
xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWAesSize), -1);
xmlSecAssert2(transformCtx != NULL, -1);
- ctx = xmlSecNssKWAesGetCtx(transform);
- xmlSecAssert2(ctx != NULL, -1);
-
- keySize = xmlSecBufferGetSize(&(ctx->keyBuffer));
- xmlSecAssert2(keySize == ctx->keyExpectedSize, -1);
+ key = xmlSecNssKWAesGetKey(transform);
+ xmlSecAssert2(key != NULL, -1);
+ keySize = xmlSecBufferGetSize(key);
+ expectedKeySize = xmlSecNssKWAesGetKeySize(transform);
+ xmlSecAssert2(keySize == expectedKeySize, -1);
+
in = &(transform->inBuf);
out = &(transform->outBuf);
inSize = xmlSecBufferGetSize(in);
- outSize = xmlSecBufferGetSize(out);
+ outSize = xmlSecBufferGetSize(out);
xmlSecAssert2(outSize == 0, -1);
-
+
if(transform->status == xmlSecTransformStatusNone) {
- transform->status = xmlSecTransformStatusWorking;
+ transform->status = xmlSecTransformStatusWorking;
}
-
+
if((transform->status == xmlSecTransformStatusWorking) && (last == 0)) {
- /* just do nothing */
+ /* just do nothing */
} else if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) {
- if((inSize % 8) != 0) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
- NULL,
- XMLSEC_ERRORS_R_INVALID_SIZE,
- "size=%d(not 8 bytes aligned)", inSize);
- return(-1);
- }
-
- if(transform->operation == xmlSecTransformOperationEncrypt) {
- /* the encoded key might be 8 bytes longer plus 8 bytes just in case */
- outSize = inSize + XMLSEC_KW_AES_MAGIC_BLOCK_SIZE +
- XMLSEC_KW_AES_BLOCK_SIZE;
- } else {
- outSize = inSize + XMLSEC_KW_AES_BLOCK_SIZE;
- }
-
- ret = xmlSecBufferSetMaxSize(out, outSize);
- if(ret < 0) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
- "xmlSecBufferSetMaxSize",
- XMLSEC_ERRORS_R_XMLSEC_FAILED,
- "outSize=%d", outSize);
- return(-1);
- }
-
- if(transform->operation == xmlSecTransformOperationEncrypt) {
- PK11SymKey *aeskey = NULL;
-
- /* create key */
- aeskey = xmlSecNssMakeAesKey(xmlSecBufferGetData(&(ctx->keyBuffer)), keySize, 1); /* encrypt */
- if(aeskey == NULL) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "xmlSecNssMakeAesKey",
- XMLSEC_ERRORS_R_CRYPTO_FAILED,
- XMLSEC_ERRORS_NO_MESSAGE);
- return(-1);
- }
-
-
- /* encrypt */
- ret = xmlSecKWAesEncode(&xmlSecNssKWAesKlass, aeskey,
- xmlSecBufferGetData(in), inSize,
- xmlSecBufferGetData(out), outSize);
- if(ret < 0) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
- "xmlSecKWAesEncode",
- XMLSEC_ERRORS_R_XMLSEC_FAILED,
- XMLSEC_ERRORS_NO_MESSAGE);
- PK11_FreeSymKey(aeskey);
- return(-1);
- }
-
- outSize = ret;
- PK11_FreeSymKey(aeskey);
- } else {
- PK11SymKey *aeskey = NULL;
-
- /* create key */
- aeskey = xmlSecNssMakeAesKey(xmlSecBufferGetData(&(ctx->keyBuffer)), keySize, 0); /* decrypt */
- if(aeskey == NULL) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "xmlSecNssMakeAesKey",
- XMLSEC_ERRORS_R_CRYPTO_FAILED,
- XMLSEC_ERRORS_NO_MESSAGE);
- return(-1);
- }
-
- /* decrypt */
- ret = xmlSecKWAesDecode(&xmlSecNssKWAesKlass, aeskey,
- xmlSecBufferGetData(in), inSize,
- xmlSecBufferGetData(out), outSize);
- if(ret < 0) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
- "xmlSecKWAesDecode",
- XMLSEC_ERRORS_R_XMLSEC_FAILED,
- XMLSEC_ERRORS_NO_MESSAGE);
- PK11_FreeSymKey(aeskey);
- return(-1);
- }
-
- outSize = ret;
- PK11_FreeSymKey(aeskey);
- }
-
- ret = xmlSecBufferSetSize(out, outSize);
- if(ret < 0) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
- "xmlSecBufferSetSize",
- XMLSEC_ERRORS_R_XMLSEC_FAILED,
- "outSize=%d", outSize);
- return(-1);
- }
-
- ret = xmlSecBufferRemoveHead(in, inSize);
- if(ret < 0) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
- "xmlSecBufferRemoveHead",
- XMLSEC_ERRORS_R_XMLSEC_FAILED,
- "inSize%d", inSize);
- return(-1);
- }
-
- transform->status = xmlSecTransformStatusFinished;
+ if((inSize % 8) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_SIZE,
+ "size=%d(not 8 bytes aligned)", inSize);
+ return(-1);
+ }
+
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ /* the encoded key might be 8 bytes longer plus 8 bytes just in case */
+ outSize = inSize + XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE +
+ XMLSEC_NSS_AES_BLOCK_SIZE;
+ } else {
+ outSize = inSize + XMLSEC_NSS_AES_BLOCK_SIZE;
+ }
+
+ ret = xmlSecBufferSetMaxSize(out, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "outSize=%d", outSize);
+ return(-1);
+ }
+
+ if(transform->operation == xmlSecTransformOperationEncrypt) {
+ ret = xmlSecNssKWAesOp(xmlSecBufferGetData(key), keySize,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize, 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecNssKWAesOp",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ outSize = ret;
+ } else {
+ ret = xmlSecNssKWAesOp(xmlSecBufferGetData(key), keySize,
+ xmlSecBufferGetData(in), inSize,
+ xmlSecBufferGetData(out), outSize, 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecNssKWAesOp",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ outSize = ret;
+ }
+
+ ret = xmlSecBufferSetSize(out, outSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "outSize=%d", outSize);
+ return(-1);
+ }
+
+ ret = xmlSecBufferRemoveHead(in, inSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecBufferRemoveHead",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "inSize%d", inSize);
+ return(-1);
+ }
+
+ transform->status = xmlSecTransformStatusFinished;
} else if(transform->status == xmlSecTransformStatusFinished) {
- /* the only way we can get here is if there is no input */
- xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1);
+ /* the only way we can get here is if there is no input */
+ xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1);
} else {
- xmlSecError(XMLSEC_ERRORS_HERE,
- xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
- NULL,
- XMLSEC_ERRORS_R_INVALID_STATUS,
- "status=%d", transform->status);
- return(-1);
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_STATUS,
+ "status=%d", transform->status);
+ return(-1);
}
return(0);
}
-/*********************************************************************
- *
- * AES KW implementation
- *
- *********************************************************************/
-static int
-xmlSecNSSKWAesBlockEncrypt(const xmlSecByte * in, xmlSecSize inSize,
- xmlSecByte * out, xmlSecSize outSize,
- void * context) {
- PK11SymKey *aeskey = (PK11SymKey *)context;
- int ret;
-
- xmlSecAssert2(in != NULL, -1);
- xmlSecAssert2(inSize >= XMLSEC_KW_AES_BLOCK_SIZE, -1);
- xmlSecAssert2(out != NULL, -1);
- xmlSecAssert2(outSize >= XMLSEC_KW_AES_BLOCK_SIZE, -1);
- xmlSecAssert2(aeskey != NULL, -1);
-
- /* one block */
- ret = xmlSecNssAesOp(aeskey, in, out, 1); /* encrypt */
- if(ret < 0) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "xmlSecNssAesOp",
- XMLSEC_ERRORS_R_XMLSEC_FAILED,
- XMLSEC_ERRORS_NO_MESSAGE);
- return(-1);
+static xmlSecSize
+xmlSecNssKWAesGetKeySize(xmlSecTransformPtr transform) {
+ if(xmlSecTransformCheckId(transform, xmlSecNssTransformKWAes128Id)) {
+ return(XMLSEC_NSS_AES128_KEY_SIZE);
+ } else if(xmlSecTransformCheckId(transform, xmlSecNssTransformKWAes192Id)) {
+ return(XMLSEC_NSS_AES192_KEY_SIZE);
+ } else if(xmlSecTransformCheckId(transform, xmlSecNssTransformKWAes256Id)) {
+ return(XMLSEC_NSS_AES256_KEY_SIZE);
}
- return(XMLSEC_KW_AES_BLOCK_SIZE);
+ return(0);
}
-static int
-xmlSecNSSKWAesBlockDecrypt(const xmlSecByte * in, xmlSecSize inSize,
- xmlSecByte * out, xmlSecSize outSize,
- void * context) {
- PK11SymKey *aeskey = (PK11SymKey *)context;
- int ret;
+/**
+ * http://www.w3.org/TR/xmlenc-core/#sec-Alg-SymmetricKeyWrap:
+ *
+ * Assume that the data to be wrapped consists of N 64-bit data blocks
+ * denoted P(1), P(2), P(3) ... P(N). The result of wrapping will be N+1
+ * 64-bit blocks denoted C(0), C(1), C(2), ... C(N). The key encrypting
+ * key is represented by K. Assume integers i, j, and t and intermediate
+ * 64-bit register A, 128-bit register B, and array of 64-bit quantities
+ * R(1) through R(N).
+ *
+ * "|" represents concatentation so x|y, where x and y and 64-bit quantities,
+ * is the 128-bit quantity with x in the most significant bits and y in the
+ * least significant bits. AES(K)enc(x) is the operation of AES encrypting
+ * the 128-bit quantity x under the key K. AES(K)dec(x) is the corresponding
+ * decryption opteration. XOR(x,y) is the bitwise exclusive or of x and y.
+ * MSB(x) and LSB(y) are the most significant 64 bits and least significant
+ * 64 bits of x and y respectively.
+ *
+ * If N is 1, a single AES operation is performed for wrap or unwrap.
+ * If N>1, then 6*N AES operations are performed for wrap or unwrap.
+ *
+ * The key wrap algorithm is as follows:
+ *
+ * 1. If N is 1:
+ * * B=AES(K)enc(0xA6A6A6A6A6A6A6A6|P(1))
+ * * C(0)=MSB(B)
+ * * C(1)=LSB(B)
+ * If N>1, perform the following steps:
+ * 2. Initialize variables:
+ * * Set A to 0xA6A6A6A6A6A6A6A6
+ * * Fori=1 to N,
+ * R(i)=P(i)
+ * 3. Calculate intermediate values:
+ * * Forj=0 to 5,
+ * o For i=1 to N,
+ * t= i + j*N
+ * B=AES(K)enc(A|R(i))
+ * A=XOR(t,MSB(B))
+ * R(i)=LSB(B)
+ * 4. Output the results:
+ * * Set C(0)=A
+ * * For i=1 to N,
+ * C(i)=R(i)
+ *
+ * The key unwrap algorithm is as follows:
+ *
+ * 1. If N is 1:
+ * * B=AES(K)dec(C(0)|C(1))
+ * * P(1)=LSB(B)
+ * * If MSB(B) is 0xA6A6A6A6A6A6A6A6, return success. Otherwise,
+ * return an integrity check failure error.
+ * If N>1, perform the following steps:
+ * 2. Initialize the variables:
+ * * A=C(0)
+ * * For i=1 to N,
+ * R(i)=C(i)
+ * 3. Calculate intermediate values:
+ * * For j=5 to 0,
+ * o For i=N to 1,
+ * t= i + j*N
+ * B=AES(K)dec(XOR(t,A)|R(i))
+ * A=MSB(B)
+ * R(i)=LSB(B)
+ * 4. Output the results:
+ * * For i=1 to N,
+ * P(i)=R(i)
+ * * If A is 0xA6A6A6A6A6A6A6A6, return success. Otherwise, return
+ * an integrity check failure error.
+ */
+#ifndef NSS_AES_KEYWRAP_BUG_FIXED
+static const xmlSecByte xmlSecNssKWAesMagicBlock[XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE] = {
+ 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6
+};
+
+static int
+xmlSecNssKWAesOp(const xmlSecByte *key, xmlSecSize keySize,
+ const xmlSecByte *in, xmlSecSize inSize,
+ xmlSecByte *out, xmlSecSize outSize, int enc) {
+ xmlSecByte block[XMLSEC_NSS_AES_BLOCK_SIZE];
+ xmlSecByte *p;
+ int N, i, j, t;
+ int result = -1;
+ PK11SymKey *aeskey = NULL;
+
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(keySize > 0, -1);
xmlSecAssert2(in != NULL, -1);
- xmlSecAssert2(inSize >= XMLSEC_KW_AES_BLOCK_SIZE, -1);
+ xmlSecAssert2(inSize > 0, -1);
xmlSecAssert2(out != NULL, -1);
- xmlSecAssert2(outSize >= XMLSEC_KW_AES_BLOCK_SIZE, -1);
- xmlSecAssert2(aeskey != NULL, -1);
+ xmlSecAssert2(outSize >= inSize + 8, -1);
+
+ if (enc == 1) {
+ aeskey = xmlSecNssMakeAesKey(key, keySize, enc);
+ if(aeskey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssMakeAesKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* prepend magic block */
+ if(in != out) {
+ memcpy(out + XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE, in, inSize);
+ } else {
+ memmove(out + XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE, out, inSize);
+ }
+ memcpy(out, xmlSecNssKWAesMagicBlock, XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE);
+
+ N = (inSize / 8);
+ if(N == 1) {
+ xmlSecNssAesOp(aeskey, out, out, enc);
+ } else {
+ for(j = 0; j <= 5; ++j) {
+ for(i = 1; i <= N; ++i) {
+ t = i + (j * N);
+ p = out + i * 8;
+
+ memcpy(block, out, 8);
+ memcpy(block + 8, p, 8);
+
+ xmlSecNssAesOp(aeskey, block, block, enc);
+ block[7] ^= t;
+ memcpy(out, block, 8);
+ memcpy(p, block + 8, 8);
+ }
+ }
+ }
+
+ result = inSize + 8;
+ } else {
+ aeskey = xmlSecNssMakeAesKey(key, keySize, enc);
+ if(aeskey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecNssMakeAesKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* copy input */
+ if(in != out) {
+ memcpy(out, in, inSize);
+ }
+
+ N = (inSize / 8) - 1;
+ if(N == 1) {
+ xmlSecNssAesOp(aeskey, out, out, enc);
+ } else {
+ for(j = 5; j >= 0; --j) {
+ for(i = N; i > 0; --i) {
+ t = i + (j * N);
+ p = out + i * 8;
+
+ memcpy(block, out, 8);
+ memcpy(block + 8, p, 8);
+ block[7] ^= t;
+
+ xmlSecNssAesOp(aeskey, block, block, enc);
+ memcpy(out, block, 8);
+ memcpy(p, block + 8, 8);
+ }
+ }
+ }
+ /* do not left data in memory */
+ memset(block, 0, sizeof(block));
+
+ if(memcmp(xmlSecNssKWAesMagicBlock, out, XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE) != 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_DATA,
+ "bad magic block");
+ goto done;
+ }
+
+ memmove(out, out + XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE, inSize - XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE);
+ result = (inSize - XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE);
+ }
- /* one block */
- ret = xmlSecNssAesOp(aeskey, in, out, 0); /* decrypt */
- if(ret < 0) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "xmlSecNssAesOp",
- XMLSEC_ERRORS_R_XMLSEC_FAILED,
- XMLSEC_ERRORS_NO_MESSAGE);
- return(-1);
+done:
+ if (aeskey != NULL) {
+ PK11_FreeSymKey(aeskey);
}
- return(XMLSEC_KW_AES_BLOCK_SIZE);
+
+ return (result);
}
static PK11SymKey *
@@ -565,45 +619,46 @@ xmlSecNssMakeAesKey(const xmlSecByte *key, xmlSecSize keySize, int enc) {
PK11SlotInfo* slot = NULL;
PK11SymKey* aeskey = NULL;
SECItem keyItem;
-
+
xmlSecAssert2(key != NULL, NULL);
xmlSecAssert2(keySize > 0, NULL);
cipherMech = CKM_AES_ECB;
slot = PK11_GetBestSlot(cipherMech, NULL);
if (slot == NULL) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "PK11_GetBestSlot",
- XMLSEC_ERRORS_R_CRYPTO_FAILED,
- XMLSEC_ERRORS_NO_MESSAGE);
- goto done;
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_GetBestSlot",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
}
keyItem.data = (unsigned char *)key;
keyItem.len = keySize;
- aeskey = PK11_ImportSymKey(slot, cipherMech, PK11_OriginUnwrap,
- enc ? CKA_ENCRYPT : CKA_DECRYPT, &keyItem, NULL);
+ aeskey = PK11_ImportSymKey(slot, cipherMech, PK11_OriginUnwrap,
+ enc ? CKA_ENCRYPT : CKA_DECRYPT, &keyItem, NULL);
if (aeskey == NULL) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "PK11_ImportSymKey",
- XMLSEC_ERRORS_R_CRYPTO_FAILED,
- XMLSEC_ERRORS_NO_MESSAGE);
- goto done;
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_ImportSymKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
}
done:
if (slot) {
- PK11_FreeSlot(slot);
+ PK11_FreeSlot(slot);
}
return(aeskey);
}
-/* encrypt a block (XMLSEC_KW_AES_BLOCK_SIZE), in and out can overlap */
-static int
-xmlSecNssAesOp(PK11SymKey *aeskey, const xmlSecByte *in, xmlSecByte *out, int enc) {
+/* encrypt a block (XMLSEC_NSS_AES_BLOCK_SIZE), in and out can overlap */
+static void
+xmlSecNssAesOp(PK11SymKey *aeskey, const xmlSecByte *in, xmlSecByte *out,
+ int enc) {
CK_MECHANISM_TYPE cipherMech;
SECItem* SecParam = NULL;
@@ -611,71 +666,192 @@ xmlSecNssAesOp(PK11SymKey *aeskey, const xmlSecByte *in, xmlSecByte *out, int en
SECStatus rv;
int tmp1_outlen;
unsigned int tmp2_outlen;
- int ret = -1;
+ xmlSecAssert(in != NULL);
+ xmlSecAssert(out != NULL);
+
+ cipherMech = CKM_AES_ECB;
+ SecParam = PK11_ParamFromIV(cipherMech, NULL);
+ if (SecParam == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_ParamFromIV",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ EncContext = PK11_CreateContextBySymKey(cipherMech,
+ enc ? CKA_ENCRYPT : CKA_DECRYPT,
+ aeskey, SecParam);
+ if (EncContext == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_CreateContextBySymKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ tmp1_outlen = tmp2_outlen = 0;
+ rv = PK11_CipherOp(EncContext, out, &tmp1_outlen,
+ XMLSEC_NSS_AES_BLOCK_SIZE, (unsigned char *)in,
+ XMLSEC_NSS_AES_BLOCK_SIZE);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_CipherOp",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ rv = PK11_DigestFinal(EncContext, out+tmp1_outlen,
+ &tmp2_outlen, XMLSEC_NSS_AES_BLOCK_SIZE-tmp1_outlen);
+ if (rv != SECSuccess) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_DigestFinal",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+done:
+ if (SecParam) {
+ SECITEM_FreeItem(SecParam, PR_TRUE);
+ }
+ if (EncContext) {
+ PK11_DestroyContext(EncContext, PR_TRUE);
+ }
+
+}
+
+#else /* NSS_AES_KEYWRAP_BUG_FIXED */
+
+/* Note: When the bug gets fixed, it is not enough to just remove
+ * the #ifdef (NSS_AES_KEYWRAP_BUG_FIXED). The code also has
+ * to change from doing the Init/Update/Final to just a straight
+ * encrypt or decrypt. PK11 wrappers have to be exposed by
+ * NSS, and these should be used.
+ * Follow the NSS bug system for more details on the fix
+ * http://bugzilla.mozilla.org/show_bug.cgi?id=213795
+ */
+
+/* NSS implements the AES Key Wrap algorithm described at
+ * http://www.w3.org/TR/xmlenc-core/#sec-Alg-SymmetricKeyWrap
+ */
+
+static int
+xmlSecNssKWAesOp(const xmlSecByte *key, xmlSecSize keySize,
+ const xmlSecByte *in, xmlSecSize inSize,
+ xmlSecByte *out, xmlSecSize outSize, int enc) {
+
+ CK_MECHANISM_TYPE cipherMech;
+ PK11SlotInfo* slot = NULL;
+ PK11SymKey* aeskey = NULL;
+ SECItem* SecParam = NULL;
+ PK11Context* EncContext = NULL;
+ SECItem keyItem;
+ SECStatus rv;
+ int result_len = -1;
+ int tmp1_outlen;
+ unsigned int tmp2_outlen;
+
+ xmlSecAssert2(key != NULL, -1);
+ xmlSecAssert2(keySize > 0, -1);
xmlSecAssert2(in != NULL, -1);
+ xmlSecAssert2(inSize > 0, -1);
xmlSecAssert2(out != NULL, -1);
+ xmlSecAssert2(outSize >= inSize + 8, -1);
+
+ cipherMech = CKM_NETSCAPE_AES_KEY_WRAP;
+ slot = PK11_GetBestSlot(cipherMech, NULL);
+ if (slot == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_GetBestSlot",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ keyItem.data = (unsigned char *)key;
+ keyItem.len = keySize;
+ aeskey = PK11_ImportSymKey(slot, cipherMech, PK11_OriginUnwrap,
+ enc ? CKA_ENCRYPT : CKA_DECRYPT, &keyItem, NULL);
+ if (aeskey == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_ImportSymKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
- cipherMech = CKM_AES_ECB;
SecParam = PK11_ParamFromIV(cipherMech, NULL);
if (SecParam == NULL) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "PK11_ParamFromIV",
- XMLSEC_ERRORS_R_CRYPTO_FAILED,
- XMLSEC_ERRORS_NO_MESSAGE);
- goto done;
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_ParamFromIV",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
}
- EncContext = PK11_CreateContextBySymKey(cipherMech,
- enc ? CKA_ENCRYPT : CKA_DECRYPT,
- aeskey, SecParam);
+ EncContext = PK11_CreateContextBySymKey(cipherMech,
+ enc ? CKA_ENCRYPT : CKA_DECRYPT,
+ aeskey, SecParam);
if (EncContext == NULL) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "PK11_CreateContextBySymKey",
- XMLSEC_ERRORS_R_CRYPTO_FAILED,
- XMLSEC_ERRORS_NO_MESSAGE);
- goto done;
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_CreateContextBySymKey",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
}
tmp1_outlen = tmp2_outlen = 0;
- rv = PK11_CipherOp(EncContext, out, &tmp1_outlen,
- XMLSEC_KW_AES_BLOCK_SIZE, (unsigned char *)in,
- XMLSEC_KW_AES_BLOCK_SIZE);
+ rv = PK11_CipherOp(EncContext, out, &tmp1_outlen, outSize,
+ (unsigned char *)in, inSize);
if (rv != SECSuccess) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "PK11_CipherOp",
- XMLSEC_ERRORS_R_CRYPTO_FAILED,
- XMLSEC_ERRORS_NO_MESSAGE);
- goto done;
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_CipherOp",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
}
- rv = PK11_DigestFinal(EncContext, out+tmp1_outlen,
- &tmp2_outlen, XMLSEC_KW_AES_BLOCK_SIZE-tmp1_outlen);
+ rv = PK11_DigestFinal(EncContext, out+tmp1_outlen,
+ &tmp2_outlen, outSize-tmp1_outlen);
if (rv != SECSuccess) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "PK11_DigestFinal",
- XMLSEC_ERRORS_R_CRYPTO_FAILED,
- XMLSEC_ERRORS_NO_MESSAGE);
- goto done;
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "PK11_DigestFinal",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
}
- /* done - success! */
- ret = 0;
+ result_len = tmp1_outlen + tmp2_outlen;
done:
+ if (slot) {
+ PK11_FreeSlot(slot);
+ }
+ if (aeskey) {
+ PK11_FreeSymKey(aeskey);
+ }
if (SecParam) {
- SECITEM_FreeItem(SecParam, PR_TRUE);
+ SECITEM_FreeItem(SecParam, PR_TRUE);
}
if (EncContext) {
- PK11_DestroyContext(EncContext, PR_TRUE);
+ PK11_DestroyContext(EncContext, PR_TRUE);
}
- return (ret);
+ return(result_len);
}
-
+#endif /* NSS_AES_KEYWRAP_BUG_FIXED */
#endif /* XMLSEC_NO_AES */