5 * AES Algorithm support
7 * This is free software; see Copyright file in the source
8 * distribution for preciese wording.
10 * Copyright (c) 2003 America Online, Inc. All rights reserved.
23 #include <xmlsec/xmlsec.h>
24 #include <xmlsec/xmltree.h>
25 #include <xmlsec/keys.h>
26 #include <xmlsec/transforms.h>
27 #include <xmlsec/errors.h>
29 #include <xmlsec/nss/crypto.h>
31 #define XMLSEC_NSS_AES128_KEY_SIZE 16
32 #define XMLSEC_NSS_AES192_KEY_SIZE 24
33 #define XMLSEC_NSS_AES256_KEY_SIZE 32
34 #define XMLSEC_NSS_AES_IV_SIZE 16
35 #define XMLSEC_NSS_AES_BLOCK_SIZE 16
37 #ifndef NSS_AES_KEYWRAP_BUG_FIXED
38 static PK11SymKey* xmlSecNssMakeAesKey(const xmlSecByte *key,
39 xmlSecSize keySize, int enc);
40 static void xmlSecNssAesOp(PK11SymKey *aeskey,
41 const xmlSecByte *in, xmlSecByte *out,
43 #endif /* NSS_AES_KEYWRAP_BUG_FIXED */
45 /*********************************************************************
49 * key (xmlSecBuffer) is located after xmlSecTransform structure
51 ********************************************************************/
52 #define xmlSecNssKWAesGetKey(transform) \
53 ((xmlSecBufferPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
54 #define xmlSecNssKWAesSize \
55 (sizeof(xmlSecTransform) + sizeof(xmlSecBuffer))
57 static int xmlSecNssKWAesInitialize (xmlSecTransformPtr transform);
58 static void xmlSecNssKWAesFinalize (xmlSecTransformPtr transform);
59 static int xmlSecNssKWAesSetKeyReq (xmlSecTransformPtr transform,
60 xmlSecKeyReqPtr keyReq);
61 static int xmlSecNssKWAesSetKey (xmlSecTransformPtr transform,
63 static int xmlSecNssKWAesExecute (xmlSecTransformPtr transform,
65 xmlSecTransformCtxPtr transformCtx);
66 static xmlSecSize xmlSecNssKWAesGetKeySize (xmlSecTransformPtr transform);
67 static int xmlSecNssKWAesOp (const xmlSecByte *key,
75 static xmlSecTransformKlass xmlSecNssKWAes128Klass = {
76 /* klass/object sizes */
77 sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
78 xmlSecNssKWAesSize, /* xmlSecSize objSize */
80 xmlSecNameKWAes128, /* const xmlChar* name; */
81 xmlSecHrefKWAes128, /* const xmlChar* href; */
82 xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
84 xmlSecNssKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */
85 xmlSecNssKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */
86 NULL, /* xmlSecTransformNodeReadMethod readNode; */
87 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
88 xmlSecNssKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
89 xmlSecNssKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */
90 NULL, /* xmlSecTransformValidateMethod validate; */
91 xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
92 xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
93 xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
94 NULL, /* xmlSecTransformPushXmlMethod pushXml; */
95 NULL, /* xmlSecTransformPopXmlMethod popXml; */
96 xmlSecNssKWAesExecute, /* xmlSecTransformExecuteMethod execute; */
98 NULL, /* void* reserved0; */
99 NULL, /* void* reserved1; */
102 static xmlSecTransformKlass xmlSecNssKWAes192Klass = {
103 /* klass/object sizes */
104 sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
105 xmlSecNssKWAesSize, /* xmlSecSize objSize */
107 xmlSecNameKWAes192, /* const xmlChar* name; */
108 xmlSecHrefKWAes192, /* const xmlChar* href; */
109 xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
111 xmlSecNssKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */
112 xmlSecNssKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */
113 NULL, /* xmlSecTransformNodeReadMethod readNode; */
114 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
115 xmlSecNssKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
116 xmlSecNssKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */
117 NULL, /* xmlSecTransformValidateMethod validate; */
118 xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
119 xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
120 xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
121 NULL, /* xmlSecTransformPushXmlMethod pushXml; */
122 NULL, /* xmlSecTransformPopXmlMethod popXml; */
123 xmlSecNssKWAesExecute, /* xmlSecTransformExecuteMethod execute; */
125 NULL, /* void* reserved0; */
126 NULL, /* void* reserved1; */
129 static xmlSecTransformKlass xmlSecNssKWAes256Klass = {
130 /* klass/object sizes */
131 sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
132 xmlSecNssKWAesSize, /* xmlSecSize objSize */
134 xmlSecNameKWAes256, /* const xmlChar* name; */
135 xmlSecHrefKWAes256, /* const xmlChar* href; */
136 xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
138 xmlSecNssKWAesInitialize, /* xmlSecTransformInitializeMethod initialize; */
139 xmlSecNssKWAesFinalize, /* xmlSecTransformFinalizeMethod finalize; */
140 NULL, /* xmlSecTransformNodeReadMethod readNode; */
141 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
142 xmlSecNssKWAesSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
143 xmlSecNssKWAesSetKey, /* xmlSecTransformSetKeyMethod setKey; */
144 NULL, /* xmlSecTransformValidateMethod validate; */
145 xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
146 xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
147 xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
148 NULL, /* xmlSecTransformPushXmlMethod pushXml; */
149 NULL, /* xmlSecTransformPopXmlMethod popXml; */
150 xmlSecNssKWAesExecute, /* xmlSecTransformExecuteMethod execute; */
152 NULL, /* void* reserved0; */
153 NULL, /* void* reserved1; */
156 #define XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE 8
158 #define xmlSecNssKWAesCheckId(transform) \
159 (xmlSecTransformCheckId((transform), xmlSecNssTransformKWAes128Id) || \
160 xmlSecTransformCheckId((transform), xmlSecNssTransformKWAes192Id) || \
161 xmlSecTransformCheckId((transform), xmlSecNssTransformKWAes256Id))
164 * xmlSecNssTransformKWAes128GetKlass:
166 * The AES-128 key wrapper transform klass.
168 * Returns: AES-128 key wrapper transform klass.
171 xmlSecNssTransformKWAes128GetKlass(void) {
172 return(&xmlSecNssKWAes128Klass);
176 * xmlSecNssTransformKWAes192GetKlass:
178 * The AES-192 key wrapper transform klass.
180 * Returns: AES-192 key wrapper transform klass.
183 xmlSecNssTransformKWAes192GetKlass(void) {
184 return(&xmlSecNssKWAes192Klass);
188 * xmlSecNssTransformKWAes256GetKlass:
190 * The AES-256 key wrapper transform klass.
192 * Returns: AES-256 key wrapper transform klass.
195 xmlSecNssTransformKWAes256GetKlass(void) {
196 return(&xmlSecNssKWAes256Klass);
200 xmlSecNssKWAesInitialize(xmlSecTransformPtr transform) {
203 xmlSecAssert2(xmlSecNssKWAesCheckId(transform), -1);
204 xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWAesSize), -1);
206 ret = xmlSecBufferInitialize(xmlSecNssKWAesGetKey(transform), 0);
208 xmlSecError(XMLSEC_ERRORS_HERE,
209 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
210 "xmlSecBufferInitialize",
211 XMLSEC_ERRORS_R_XMLSEC_FAILED,
212 XMLSEC_ERRORS_NO_MESSAGE);
220 xmlSecNssKWAesFinalize(xmlSecTransformPtr transform) {
221 xmlSecAssert(xmlSecNssKWAesCheckId(transform));
222 xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecNssKWAesSize));
224 if(xmlSecNssKWAesGetKey(transform) != NULL) {
225 xmlSecBufferFinalize(xmlSecNssKWAesGetKey(transform));
230 xmlSecNssKWAesSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
231 xmlSecAssert2(xmlSecNssKWAesCheckId(transform), -1);
232 xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
233 xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWAesSize), -1);
234 xmlSecAssert2(keyReq != NULL, -1);
236 keyReq->keyId = xmlSecNssKeyDataAesId;
237 keyReq->keyType = xmlSecKeyDataTypeSymmetric;
238 if(transform->operation == xmlSecTransformOperationEncrypt) {
239 keyReq->keyUsage = xmlSecKeyUsageEncrypt;
241 keyReq->keyUsage = xmlSecKeyUsageDecrypt;
243 keyReq->keyBitsSize = 8 * xmlSecNssKWAesGetKeySize(transform);
249 xmlSecNssKWAesSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
250 xmlSecBufferPtr buffer;
252 xmlSecSize expectedKeySize;
255 xmlSecAssert2(xmlSecNssKWAesCheckId(transform), -1);
256 xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
257 xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWAesSize), -1);
258 xmlSecAssert2(xmlSecNssKWAesGetKey(transform) != NULL, -1);
259 xmlSecAssert2(key != NULL, -1);
260 xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecNssKeyDataAesId), -1);
262 buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key));
263 xmlSecAssert2(buffer != NULL, -1);
265 keySize = xmlSecBufferGetSize(buffer);
266 expectedKeySize = xmlSecNssKWAesGetKeySize(transform);
267 if(keySize < expectedKeySize) {
268 xmlSecError(XMLSEC_ERRORS_HERE,
269 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
271 XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,
272 "key=%d;expected=%d",
273 keySize, expectedKeySize);
277 ret = xmlSecBufferSetData(xmlSecNssKWAesGetKey(transform),
278 xmlSecBufferGetData(buffer),
281 xmlSecError(XMLSEC_ERRORS_HERE,
282 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
283 "xmlSecBufferSetData",
284 XMLSEC_ERRORS_R_XMLSEC_FAILED,
285 "expected-size=%d", expectedKeySize);
293 xmlSecNssKWAesExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
294 xmlSecBufferPtr in, out, key;
295 xmlSecSize inSize, outSize, keySize, expectedKeySize;
298 xmlSecAssert2(xmlSecNssKWAesCheckId(transform), -1);
299 xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
300 xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssKWAesSize), -1);
301 xmlSecAssert2(transformCtx != NULL, -1);
303 key = xmlSecNssKWAesGetKey(transform);
304 xmlSecAssert2(key != NULL, -1);
306 keySize = xmlSecBufferGetSize(key);
307 expectedKeySize = xmlSecNssKWAesGetKeySize(transform);
308 xmlSecAssert2(keySize == expectedKeySize, -1);
310 in = &(transform->inBuf);
311 out = &(transform->outBuf);
312 inSize = xmlSecBufferGetSize(in);
313 outSize = xmlSecBufferGetSize(out);
314 xmlSecAssert2(outSize == 0, -1);
316 if(transform->status == xmlSecTransformStatusNone) {
317 transform->status = xmlSecTransformStatusWorking;
320 if((transform->status == xmlSecTransformStatusWorking) && (last == 0)) {
321 /* just do nothing */
322 } else if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) {
323 if((inSize % 8) != 0) {
324 xmlSecError(XMLSEC_ERRORS_HERE,
325 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
327 XMLSEC_ERRORS_R_INVALID_SIZE,
328 "size=%d(not 8 bytes aligned)", inSize);
332 if(transform->operation == xmlSecTransformOperationEncrypt) {
333 /* the encoded key might be 8 bytes longer plus 8 bytes just in case */
334 outSize = inSize + XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE +
335 XMLSEC_NSS_AES_BLOCK_SIZE;
337 outSize = inSize + XMLSEC_NSS_AES_BLOCK_SIZE;
340 ret = xmlSecBufferSetMaxSize(out, outSize);
342 xmlSecError(XMLSEC_ERRORS_HERE,
343 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
344 "xmlSecBufferSetMaxSize",
345 XMLSEC_ERRORS_R_XMLSEC_FAILED,
346 "outSize=%d", outSize);
350 if(transform->operation == xmlSecTransformOperationEncrypt) {
351 ret = xmlSecNssKWAesOp(xmlSecBufferGetData(key), keySize,
352 xmlSecBufferGetData(in), inSize,
353 xmlSecBufferGetData(out), outSize, 1);
355 xmlSecError(XMLSEC_ERRORS_HERE,
356 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
358 XMLSEC_ERRORS_R_XMLSEC_FAILED,
359 XMLSEC_ERRORS_NO_MESSAGE);
364 ret = xmlSecNssKWAesOp(xmlSecBufferGetData(key), keySize,
365 xmlSecBufferGetData(in), inSize,
366 xmlSecBufferGetData(out), outSize, 0);
368 xmlSecError(XMLSEC_ERRORS_HERE,
369 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
371 XMLSEC_ERRORS_R_XMLSEC_FAILED,
372 XMLSEC_ERRORS_NO_MESSAGE);
378 ret = xmlSecBufferSetSize(out, outSize);
380 xmlSecError(XMLSEC_ERRORS_HERE,
381 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
382 "xmlSecBufferSetSize",
383 XMLSEC_ERRORS_R_XMLSEC_FAILED,
384 "outSize=%d", outSize);
388 ret = xmlSecBufferRemoveHead(in, inSize);
390 xmlSecError(XMLSEC_ERRORS_HERE,
391 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
392 "xmlSecBufferRemoveHead",
393 XMLSEC_ERRORS_R_XMLSEC_FAILED,
398 transform->status = xmlSecTransformStatusFinished;
399 } else if(transform->status == xmlSecTransformStatusFinished) {
400 /* the only way we can get here is if there is no input */
401 xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1);
403 xmlSecError(XMLSEC_ERRORS_HERE,
404 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
406 XMLSEC_ERRORS_R_INVALID_STATUS,
407 "status=%d", transform->status);
414 xmlSecNssKWAesGetKeySize(xmlSecTransformPtr transform) {
415 if(xmlSecTransformCheckId(transform, xmlSecNssTransformKWAes128Id)) {
416 return(XMLSEC_NSS_AES128_KEY_SIZE);
417 } else if(xmlSecTransformCheckId(transform, xmlSecNssTransformKWAes192Id)) {
418 return(XMLSEC_NSS_AES192_KEY_SIZE);
419 } else if(xmlSecTransformCheckId(transform, xmlSecNssTransformKWAes256Id)) {
420 return(XMLSEC_NSS_AES256_KEY_SIZE);
426 * http://www.w3.org/TR/xmlenc-core/#sec-Alg-SymmetricKeyWrap:
428 * Assume that the data to be wrapped consists of N 64-bit data blocks
429 * denoted P(1), P(2), P(3) ... P(N). The result of wrapping will be N+1
430 * 64-bit blocks denoted C(0), C(1), C(2), ... C(N). The key encrypting
431 * key is represented by K. Assume integers i, j, and t and intermediate
432 * 64-bit register A, 128-bit register B, and array of 64-bit quantities
435 * "|" represents concatentation so x|y, where x and y and 64-bit quantities,
436 * is the 128-bit quantity with x in the most significant bits and y in the
437 * least significant bits. AES(K)enc(x) is the operation of AES encrypting
438 * the 128-bit quantity x under the key K. AES(K)dec(x) is the corresponding
439 * decryption opteration. XOR(x,y) is the bitwise exclusive or of x and y.
440 * MSB(x) and LSB(y) are the most significant 64 bits and least significant
441 * 64 bits of x and y respectively.
443 * If N is 1, a single AES operation is performed for wrap or unwrap.
444 * If N>1, then 6*N AES operations are performed for wrap or unwrap.
446 * The key wrap algorithm is as follows:
449 * * B=AES(K)enc(0xA6A6A6A6A6A6A6A6|P(1))
452 * If N>1, perform the following steps:
453 * 2. Initialize variables:
454 * * Set A to 0xA6A6A6A6A6A6A6A6
457 * 3. Calculate intermediate values:
461 * B=AES(K)enc(A|R(i))
464 * 4. Output the results:
469 * The key unwrap algorithm is as follows:
472 * * B=AES(K)dec(C(0)|C(1))
474 * * If MSB(B) is 0xA6A6A6A6A6A6A6A6, return success. Otherwise,
475 * return an integrity check failure error.
476 * If N>1, perform the following steps:
477 * 2. Initialize the variables:
481 * 3. Calculate intermediate values:
485 * B=AES(K)dec(XOR(t,A)|R(i))
488 * 4. Output the results:
491 * * If A is 0xA6A6A6A6A6A6A6A6, return success. Otherwise, return
492 * an integrity check failure error.
495 #ifndef NSS_AES_KEYWRAP_BUG_FIXED
496 static const xmlSecByte xmlSecNssKWAesMagicBlock[XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE] = {
497 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6
501 xmlSecNssKWAesOp(const xmlSecByte *key, xmlSecSize keySize,
502 const xmlSecByte *in, xmlSecSize inSize,
503 xmlSecByte *out, xmlSecSize outSize, int enc) {
504 xmlSecByte block[XMLSEC_NSS_AES_BLOCK_SIZE];
508 PK11SymKey *aeskey = NULL;
510 xmlSecAssert2(key != NULL, -1);
511 xmlSecAssert2(keySize > 0, -1);
512 xmlSecAssert2(in != NULL, -1);
513 xmlSecAssert2(inSize > 0, -1);
514 xmlSecAssert2(out != NULL, -1);
515 xmlSecAssert2(outSize >= inSize + 8, -1);
518 aeskey = xmlSecNssMakeAesKey(key, keySize, enc);
520 xmlSecError(XMLSEC_ERRORS_HERE,
522 "xmlSecNssMakeAesKey",
523 XMLSEC_ERRORS_R_CRYPTO_FAILED,
524 XMLSEC_ERRORS_NO_MESSAGE);
528 /* prepend magic block */
530 memcpy(out + XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE, in, inSize);
532 memmove(out + XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE, out, inSize);
534 memcpy(out, xmlSecNssKWAesMagicBlock, XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE);
538 xmlSecNssAesOp(aeskey, out, out, enc);
540 for(j = 0; j <= 5; ++j) {
541 for(i = 1; i <= N; ++i) {
545 memcpy(block, out, 8);
546 memcpy(block + 8, p, 8);
548 xmlSecNssAesOp(aeskey, block, block, enc);
550 memcpy(out, block, 8);
551 memcpy(p, block + 8, 8);
558 aeskey = xmlSecNssMakeAesKey(key, keySize, enc);
560 xmlSecError(XMLSEC_ERRORS_HERE,
562 "xmlSecNssMakeAesKey",
563 XMLSEC_ERRORS_R_CRYPTO_FAILED,
564 XMLSEC_ERRORS_NO_MESSAGE);
570 memcpy(out, in, inSize);
573 N = (inSize / 8) - 1;
575 xmlSecNssAesOp(aeskey, out, out, enc);
577 for(j = 5; j >= 0; --j) {
578 for(i = N; i > 0; --i) {
582 memcpy(block, out, 8);
583 memcpy(block + 8, p, 8);
586 xmlSecNssAesOp(aeskey, block, block, enc);
587 memcpy(out, block, 8);
588 memcpy(p, block + 8, 8);
592 /* do not left data in memory */
593 memset(block, 0, sizeof(block));
595 if(memcmp(xmlSecNssKWAesMagicBlock, out, XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE) != 0) {
596 xmlSecError(XMLSEC_ERRORS_HERE,
599 XMLSEC_ERRORS_R_INVALID_DATA,
604 memmove(out, out + XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE, inSize - XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE);
605 result = (inSize - XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE);
609 if (aeskey != NULL) {
610 PK11_FreeSymKey(aeskey);
617 xmlSecNssMakeAesKey(const xmlSecByte *key, xmlSecSize keySize, int enc) {
618 CK_MECHANISM_TYPE cipherMech;
619 PK11SlotInfo* slot = NULL;
620 PK11SymKey* aeskey = NULL;
623 xmlSecAssert2(key != NULL, NULL);
624 xmlSecAssert2(keySize > 0, NULL);
626 cipherMech = CKM_AES_ECB;
627 slot = PK11_GetBestSlot(cipherMech, NULL);
629 xmlSecError(XMLSEC_ERRORS_HERE,
632 XMLSEC_ERRORS_R_CRYPTO_FAILED,
633 XMLSEC_ERRORS_NO_MESSAGE);
637 keyItem.data = (unsigned char *)key;
638 keyItem.len = keySize;
639 aeskey = PK11_ImportSymKey(slot, cipherMech, PK11_OriginUnwrap,
640 enc ? CKA_ENCRYPT : CKA_DECRYPT, &keyItem, NULL);
641 if (aeskey == NULL) {
642 xmlSecError(XMLSEC_ERRORS_HERE,
645 XMLSEC_ERRORS_R_CRYPTO_FAILED,
646 XMLSEC_ERRORS_NO_MESSAGE);
658 /* encrypt a block (XMLSEC_NSS_AES_BLOCK_SIZE), in and out can overlap */
660 xmlSecNssAesOp(PK11SymKey *aeskey, const xmlSecByte *in, xmlSecByte *out,
663 CK_MECHANISM_TYPE cipherMech;
664 SECItem* SecParam = NULL;
665 PK11Context* EncContext = NULL;
668 unsigned int tmp2_outlen;
670 xmlSecAssert(in != NULL);
671 xmlSecAssert(out != NULL);
673 cipherMech = CKM_AES_ECB;
674 SecParam = PK11_ParamFromIV(cipherMech, NULL);
675 if (SecParam == NULL) {
676 xmlSecError(XMLSEC_ERRORS_HERE,
679 XMLSEC_ERRORS_R_CRYPTO_FAILED,
680 XMLSEC_ERRORS_NO_MESSAGE);
684 EncContext = PK11_CreateContextBySymKey(cipherMech,
685 enc ? CKA_ENCRYPT : CKA_DECRYPT,
687 if (EncContext == NULL) {
688 xmlSecError(XMLSEC_ERRORS_HERE,
690 "PK11_CreateContextBySymKey",
691 XMLSEC_ERRORS_R_CRYPTO_FAILED,
692 XMLSEC_ERRORS_NO_MESSAGE);
696 tmp1_outlen = tmp2_outlen = 0;
697 rv = PK11_CipherOp(EncContext, out, &tmp1_outlen,
698 XMLSEC_NSS_AES_BLOCK_SIZE, (unsigned char *)in,
699 XMLSEC_NSS_AES_BLOCK_SIZE);
700 if (rv != SECSuccess) {
701 xmlSecError(XMLSEC_ERRORS_HERE,
704 XMLSEC_ERRORS_R_CRYPTO_FAILED,
705 XMLSEC_ERRORS_NO_MESSAGE);
709 rv = PK11_DigestFinal(EncContext, out+tmp1_outlen,
710 &tmp2_outlen, XMLSEC_NSS_AES_BLOCK_SIZE-tmp1_outlen);
711 if (rv != SECSuccess) {
712 xmlSecError(XMLSEC_ERRORS_HERE,
715 XMLSEC_ERRORS_R_CRYPTO_FAILED,
716 XMLSEC_ERRORS_NO_MESSAGE);
722 SECITEM_FreeItem(SecParam, PR_TRUE);
725 PK11_DestroyContext(EncContext, PR_TRUE);
730 #else /* NSS_AES_KEYWRAP_BUG_FIXED */
732 /* Note: When the bug gets fixed, it is not enough to just remove
733 * the #ifdef (NSS_AES_KEYWRAP_BUG_FIXED). The code also has
734 * to change from doing the Init/Update/Final to just a straight
735 * encrypt or decrypt. PK11 wrappers have to be exposed by
736 * NSS, and these should be used.
737 * Follow the NSS bug system for more details on the fix
738 * http://bugzilla.mozilla.org/show_bug.cgi?id=213795
741 /* NSS implements the AES Key Wrap algorithm described at
742 * http://www.w3.org/TR/xmlenc-core/#sec-Alg-SymmetricKeyWrap
746 xmlSecNssKWAesOp(const xmlSecByte *key, xmlSecSize keySize,
747 const xmlSecByte *in, xmlSecSize inSize,
748 xmlSecByte *out, xmlSecSize outSize, int enc) {
750 CK_MECHANISM_TYPE cipherMech;
751 PK11SlotInfo* slot = NULL;
752 PK11SymKey* aeskey = NULL;
753 SECItem* SecParam = NULL;
754 PK11Context* EncContext = NULL;
759 unsigned int tmp2_outlen;
761 xmlSecAssert2(key != NULL, -1);
762 xmlSecAssert2(keySize > 0, -1);
763 xmlSecAssert2(in != NULL, -1);
764 xmlSecAssert2(inSize > 0, -1);
765 xmlSecAssert2(out != NULL, -1);
766 xmlSecAssert2(outSize >= inSize + 8, -1);
768 cipherMech = CKM_NETSCAPE_AES_KEY_WRAP;
769 slot = PK11_GetBestSlot(cipherMech, NULL);
771 xmlSecError(XMLSEC_ERRORS_HERE,
774 XMLSEC_ERRORS_R_CRYPTO_FAILED,
775 XMLSEC_ERRORS_NO_MESSAGE);
779 keyItem.data = (unsigned char *)key;
780 keyItem.len = keySize;
781 aeskey = PK11_ImportSymKey(slot, cipherMech, PK11_OriginUnwrap,
782 enc ? CKA_ENCRYPT : CKA_DECRYPT, &keyItem, NULL);
783 if (aeskey == NULL) {
784 xmlSecError(XMLSEC_ERRORS_HERE,
787 XMLSEC_ERRORS_R_CRYPTO_FAILED,
788 XMLSEC_ERRORS_NO_MESSAGE);
792 SecParam = PK11_ParamFromIV(cipherMech, NULL);
793 if (SecParam == NULL) {
794 xmlSecError(XMLSEC_ERRORS_HERE,
797 XMLSEC_ERRORS_R_CRYPTO_FAILED,
798 XMLSEC_ERRORS_NO_MESSAGE);
802 EncContext = PK11_CreateContextBySymKey(cipherMech,
803 enc ? CKA_ENCRYPT : CKA_DECRYPT,
805 if (EncContext == NULL) {
806 xmlSecError(XMLSEC_ERRORS_HERE,
808 "PK11_CreateContextBySymKey",
809 XMLSEC_ERRORS_R_CRYPTO_FAILED,
810 XMLSEC_ERRORS_NO_MESSAGE);
814 tmp1_outlen = tmp2_outlen = 0;
815 rv = PK11_CipherOp(EncContext, out, &tmp1_outlen, outSize,
816 (unsigned char *)in, inSize);
817 if (rv != SECSuccess) {
818 xmlSecError(XMLSEC_ERRORS_HERE,
821 XMLSEC_ERRORS_R_CRYPTO_FAILED,
822 XMLSEC_ERRORS_NO_MESSAGE);
826 rv = PK11_DigestFinal(EncContext, out+tmp1_outlen,
827 &tmp2_outlen, outSize-tmp1_outlen);
828 if (rv != SECSuccess) {
829 xmlSecError(XMLSEC_ERRORS_HERE,
832 XMLSEC_ERRORS_R_CRYPTO_FAILED,
833 XMLSEC_ERRORS_NO_MESSAGE);
837 result_len = tmp1_outlen + tmp2_outlen;
844 PK11_FreeSymKey(aeskey);
847 SECITEM_FreeItem(SecParam, PR_TRUE);
850 PK11_DestroyContext(EncContext, PR_TRUE);
855 #endif /* NSS_AES_KEYWRAP_BUG_FIXED */
857 #endif /* XMLSEC_NO_AES */