Git init
[external/xmlsec1.git] / src / openssl / kw_aes.c
1 /** 
2  *
3  * XMLSec library
4  * 
5  * AES Algorithm support
6  * 
7  * This is free software; see Copyright file in the source
8  * distribution for preciese wording.
9  * 
10  * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
11  */
12 #ifndef XMLSEC_NO_AES
13 #ifndef XMLSEC_OPENSSL_096
14 #include "globals.h"
15
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <string.h>
19
20 #include <openssl/aes.h>
21 #include <openssl/rand.h>
22
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>
28
29 #include <xmlsec/openssl/crypto.h>
30
31 #define XMLSEC_OPENSSL_AES128_KEY_SIZE                  16
32 #define XMLSEC_OPENSSL_AES192_KEY_SIZE                  24
33 #define XMLSEC_OPENSSL_AES256_KEY_SIZE                  32
34 #define XMLSEC_OPENSSL_AES_IV_SIZE                      16
35 #define XMLSEC_OPENSSL_AES_BLOCK_SIZE                   16
36
37
38 /*********************************************************************
39  *
40  * AES KW transforms
41  *
42  * key (xmlSecBuffer) is located after xmlSecTransform structure
43  *
44  ********************************************************************/
45 #define xmlSecOpenSSLKWAesGetKey(transform) \
46     ((xmlSecBufferPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
47 #define xmlSecOpenSSLKWAesSize  \
48     (sizeof(xmlSecTransform) + sizeof(xmlSecBuffer))
49
50 static int      xmlSecOpenSSLKWAesInitialize                    (xmlSecTransformPtr transform);
51 static void     xmlSecOpenSSLKWAesFinalize                      (xmlSecTransformPtr transform);
52 static int      xmlSecOpenSSLKWAesSetKeyReq                     (xmlSecTransformPtr transform, 
53                                                                  xmlSecKeyReqPtr keyReq);
54 static int      xmlSecOpenSSLKWAesSetKey                        (xmlSecTransformPtr transform, 
55                                                                  xmlSecKeyPtr key);
56 static int      xmlSecOpenSSLKWAesExecute                       (xmlSecTransformPtr transform, 
57                                                                  int last,
58                                                                  xmlSecTransformCtxPtr transformCtx);
59 static xmlSecSize       xmlSecOpenSSLKWAesGetKeySize                    (xmlSecTransformPtr transform);
60 static int      xmlSecOpenSSLKWAesEncode                        (const xmlSecByte *key,
61                                                                  xmlSecSize keySize,
62                                                                  const xmlSecByte* in,
63                                                                  xmlSecSize inSize,
64                                                                  xmlSecByte* out,
65                                                                  xmlSecSize outSize);
66 static int      xmlSecOpenSSLKWAesDecode                        (const xmlSecByte *key,
67                                                                  xmlSecSize keySize,
68                                                                  const xmlSecByte* in,
69                                                                  xmlSecSize inSize,
70                                                                  xmlSecByte* out,
71                                                                  xmlSecSize outSize);
72
73 static xmlSecTransformKlass xmlSecOpenSSLKWAes128Klass = {
74     /* klass/object sizes */
75     sizeof(xmlSecTransformKlass),               /* xmlSecSize klassSize */
76     xmlSecOpenSSLKWAesSize,                     /* xmlSecSize objSize */
77
78     xmlSecNameKWAes128,                         /* const xmlChar* name; */
79     xmlSecHrefKWAes128,                         /* const xmlChar* href; */
80     xmlSecTransformUsageEncryptionMethod,       /* xmlSecAlgorithmUsage usage; */
81
82     xmlSecOpenSSLKWAesInitialize,               /* xmlSecTransformInitializeMethod initialize; */
83     xmlSecOpenSSLKWAesFinalize,                 /* xmlSecTransformFinalizeMethod finalize; */
84     NULL,                                       /* xmlSecTransformNodeReadMethod readNode; */
85     NULL,                                       /* xmlSecTransformNodeWriteMethod writeNode; */
86     xmlSecOpenSSLKWAesSetKeyReq,                /* xmlSecTransformSetKeyMethod setKeyReq; */
87     xmlSecOpenSSLKWAesSetKey,                   /* xmlSecTransformSetKeyMethod setKey; */
88     NULL,                                       /* xmlSecTransformValidateMethod validate; */
89     xmlSecTransformDefaultGetDataType,          /* xmlSecTransformGetDataTypeMethod getDataType; */
90     xmlSecTransformDefaultPushBin,              /* xmlSecTransformPushBinMethod pushBin; */
91     xmlSecTransformDefaultPopBin,               /* xmlSecTransformPopBinMethod popBin; */
92     NULL,                                       /* xmlSecTransformPushXmlMethod pushXml; */
93     NULL,                                       /* xmlSecTransformPopXmlMethod popXml; */
94     xmlSecOpenSSLKWAesExecute,                  /* xmlSecTransformExecuteMethod execute; */
95     
96     NULL,                                       /* void* reserved0; */
97     NULL,                                       /* void* reserved1; */
98 };
99
100 static xmlSecTransformKlass xmlSecOpenSSLKWAes192Klass = {
101     /* klass/object sizes */
102     sizeof(xmlSecTransformKlass),               /* xmlSecSize klassSize */
103     xmlSecOpenSSLKWAesSize,                     /* xmlSecSize objSize */
104
105     xmlSecNameKWAes192,                         /* const xmlChar* name; */
106     xmlSecHrefKWAes192,                         /* const xmlChar* href; */
107     xmlSecTransformUsageEncryptionMethod,       /* xmlSecAlgorithmUsage usage; */
108
109     xmlSecOpenSSLKWAesInitialize,               /* xmlSecTransformInitializeMethod initialize; */
110     xmlSecOpenSSLKWAesFinalize,                 /* xmlSecTransformFinalizeMethod finalize; */
111     NULL,                                       /* xmlSecTransformNodeReadMethod readNode; */
112     NULL,                                       /* xmlSecTransformNodeWriteMethod writeNode; */
113     xmlSecOpenSSLKWAesSetKeyReq,                /* xmlSecTransformSetKeyMethod setKeyReq; */
114     xmlSecOpenSSLKWAesSetKey,                   /* xmlSecTransformSetKeyMethod setKey; */
115     NULL,                                       /* xmlSecTransformValidateMethod validate; */
116     xmlSecTransformDefaultGetDataType,          /* xmlSecTransformGetDataTypeMethod getDataType; */
117     xmlSecTransformDefaultPushBin,              /* xmlSecTransformPushBinMethod pushBin; */
118     xmlSecTransformDefaultPopBin,               /* xmlSecTransformPopBinMethod popBin; */
119     NULL,                                       /* xmlSecTransformPushXmlMethod pushXml; */
120     NULL,                                       /* xmlSecTransformPopXmlMethod popXml; */
121     xmlSecOpenSSLKWAesExecute,                  /* xmlSecTransformExecuteMethod execute; */
122     
123     NULL,                                       /* void* reserved0; */
124     NULL,                                       /* void* reserved1; */
125 };
126
127 static xmlSecTransformKlass xmlSecOpenSSLKWAes256Klass = {
128     /* klass/object sizes */
129     sizeof(xmlSecTransformKlass),               /* xmlSecSize klassSize */
130     xmlSecOpenSSLKWAesSize,                     /* xmlSecSize objSize */
131
132     xmlSecNameKWAes256,                         /* const xmlChar* name; */
133     xmlSecHrefKWAes256,                         /* const xmlChar* href; */
134     xmlSecTransformUsageEncryptionMethod,       /* xmlSecAlgorithmUsage usage; */
135
136     xmlSecOpenSSLKWAesInitialize,               /* xmlSecTransformInitializeMethod initialize; */
137     xmlSecOpenSSLKWAesFinalize,                 /* xmlSecTransformFinalizeMethod finalize; */
138     NULL,                                       /* xmlSecTransformNodeReadMethod readNode; */
139     NULL,                                       /* xmlSecTransformNodeWriteMethod writeNode; */
140     xmlSecOpenSSLKWAesSetKeyReq,                /* xmlSecTransformSetKeyMethod setKeyReq; */
141     xmlSecOpenSSLKWAesSetKey,                   /* xmlSecTransformSetKeyMethod setKey; */
142     NULL,                                       /* xmlSecTransformValidateMethod validate; */
143     xmlSecTransformDefaultGetDataType,          /* xmlSecTransformGetDataTypeMethod getDataType; */
144     xmlSecTransformDefaultPushBin,              /* xmlSecTransformPushBinMethod pushBin; */
145     xmlSecTransformDefaultPopBin,               /* xmlSecTransformPopBinMethod popBin; */
146     NULL,                                       /* xmlSecTransformPushXmlMethod pushXml; */
147     NULL,                                       /* xmlSecTransformPopXmlMethod popXml; */
148     xmlSecOpenSSLKWAesExecute,                  /* xmlSecTransformExecuteMethod execute; */
149     
150     NULL,                                       /* void* reserved0; */
151     NULL,                                       /* void* reserved1; */
152 };
153
154 #define XMLSEC_OPENSSL_KW_AES_MAGIC_BLOCK_SIZE          8
155
156 #define xmlSecOpenSSLKWAesCheckId(transform) \
157     (xmlSecTransformCheckId((transform), xmlSecOpenSSLTransformKWAes128Id) || \
158      xmlSecTransformCheckId((transform), xmlSecOpenSSLTransformKWAes192Id) || \
159      xmlSecTransformCheckId((transform), xmlSecOpenSSLTransformKWAes256Id))
160
161 /** 
162  * xmlSecOpenSSLTransformKWAes128GetKlass:
163  *
164  * The AES-128 kew wrapper transform klass.
165  *
166  * Returns: AES-128 kew wrapper transform klass.
167  */
168 xmlSecTransformId 
169 xmlSecOpenSSLTransformKWAes128GetKlass(void) {
170     return(&xmlSecOpenSSLKWAes128Klass);
171 }
172
173 /** 
174  * xmlSecOpenSSLTransformKWAes192GetKlass:
175  *
176  * The AES-192 kew wrapper transform klass.
177  *
178  * Returns: AES-192 kew wrapper transform klass.
179  */
180 xmlSecTransformId 
181 xmlSecOpenSSLTransformKWAes192GetKlass(void) {
182     return(&xmlSecOpenSSLKWAes192Klass);
183 }
184
185 /** 
186  * xmlSecOpenSSLTransformKWAes256GetKlass:
187  *
188  * The AES-256 kew wrapper transform klass.
189  *
190  * Returns: AES-256 kew wrapper transform klass.
191  */
192 xmlSecTransformId 
193 xmlSecOpenSSLTransformKWAes256GetKlass(void) {
194     return(&xmlSecOpenSSLKWAes256Klass);
195 }
196
197 static int 
198 xmlSecOpenSSLKWAesInitialize(xmlSecTransformPtr transform) {
199     int ret;
200     
201     xmlSecAssert2(xmlSecOpenSSLKWAesCheckId(transform), -1);
202     xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWAesSize), -1);
203     
204     ret = xmlSecBufferInitialize(xmlSecOpenSSLKWAesGetKey(transform), 0);
205     if(ret < 0) {
206         xmlSecError(XMLSEC_ERRORS_HERE,
207                     xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
208                     "xmlSecOpenSSLKWAesGetKey",
209                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
210                     XMLSEC_ERRORS_NO_MESSAGE);
211         return(-1);
212     }
213         
214     return(0);
215 }
216
217 static void 
218 xmlSecOpenSSLKWAesFinalize(xmlSecTransformPtr transform) {
219     xmlSecAssert(xmlSecOpenSSLKWAesCheckId(transform));
220     xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWAesSize));
221     
222     if(xmlSecOpenSSLKWAesGetKey(transform) != NULL) {
223         xmlSecBufferFinalize(xmlSecOpenSSLKWAesGetKey(transform));
224     }
225 }
226
227 static int  
228 xmlSecOpenSSLKWAesSetKeyReq(xmlSecTransformPtr transform,  xmlSecKeyReqPtr keyReq) {
229     xmlSecAssert2(xmlSecOpenSSLKWAesCheckId(transform), -1);
230     xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
231     xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWAesSize), -1);
232     xmlSecAssert2(keyReq != NULL, -1);
233
234     keyReq->keyId        = xmlSecOpenSSLKeyDataAesId;
235     keyReq->keyType  = xmlSecKeyDataTypeSymmetric;
236     if(transform->operation == xmlSecTransformOperationEncrypt) {
237         keyReq->keyUsage = xmlSecKeyUsageEncrypt;
238     } else {
239         keyReq->keyUsage = xmlSecKeyUsageDecrypt;
240     }
241     keyReq->keyBitsSize = 8 * xmlSecOpenSSLKWAesGetKeySize(transform);
242     
243     return(0);
244 }
245
246 static int      
247 xmlSecOpenSSLKWAesSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
248     xmlSecBufferPtr buffer;
249     xmlSecSize keySize;
250     xmlSecSize expectedKeySize;
251     int ret;
252     
253     xmlSecAssert2(xmlSecOpenSSLKWAesCheckId(transform), -1);
254     xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
255     xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWAesSize), -1);
256     xmlSecAssert2(xmlSecOpenSSLKWAesGetKey(transform) != NULL, -1);
257     xmlSecAssert2(key != NULL, -1);
258     xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecOpenSSLKeyDataAesId), -1);
259     
260     buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key));
261     xmlSecAssert2(buffer != NULL, -1);
262
263     keySize = xmlSecBufferGetSize(buffer);
264     expectedKeySize = xmlSecOpenSSLKWAesGetKeySize(transform);
265     if(keySize < expectedKeySize) {
266         xmlSecError(XMLSEC_ERRORS_HERE,
267                     xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
268                     NULL,
269                     XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,
270                     "key=%d;expected=%d",
271                     keySize, expectedKeySize);
272         return(-1);
273     }
274         
275     ret = xmlSecBufferSetData(xmlSecOpenSSLKWAesGetKey(transform),
276                             xmlSecBufferGetData(buffer), 
277                             expectedKeySize);
278     if(ret < 0) {
279         xmlSecError(XMLSEC_ERRORS_HERE, 
280                     xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
281                     "xmlSecBufferSetData",
282                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
283                     "expected-size=%d", expectedKeySize);
284         return(-1);    
285     }
286
287     return(0);
288 }
289
290 static int 
291 xmlSecOpenSSLKWAesExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
292     xmlSecBufferPtr in, out, key;
293     xmlSecSize inSize, outSize, keySize, expectedKeySize;
294     int ret;
295
296     xmlSecAssert2(xmlSecOpenSSLKWAesCheckId(transform), -1);
297     xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
298     xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKWAesSize), -1);
299     xmlSecAssert2(transformCtx != NULL, -1);
300
301     key = xmlSecOpenSSLKWAesGetKey(transform);
302     xmlSecAssert2(key != NULL, -1);
303
304     keySize = xmlSecBufferGetSize(key);
305     expectedKeySize = xmlSecOpenSSLKWAesGetKeySize(transform);
306     xmlSecAssert2(keySize == expectedKeySize, -1);
307     
308     in = &(transform->inBuf);
309     out = &(transform->outBuf);
310     inSize = xmlSecBufferGetSize(in);
311     outSize = xmlSecBufferGetSize(out);    
312     xmlSecAssert2(outSize == 0, -1);
313     
314     if(transform->status == xmlSecTransformStatusNone) {
315         transform->status = xmlSecTransformStatusWorking;
316     }
317     
318     if((transform->status == xmlSecTransformStatusWorking) && (last == 0)) {
319         /* just do nothing */
320     } else  if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) {
321         if((inSize % 8) != 0) {
322             xmlSecError(XMLSEC_ERRORS_HERE,
323                         xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
324                         NULL,
325                         XMLSEC_ERRORS_R_INVALID_SIZE,
326                         "size=%d(not 8 bytes aligned)", inSize);
327             return(-1);
328         }       
329         
330         if(transform->operation == xmlSecTransformOperationEncrypt) {
331             /* the encoded key might be 8 bytes longer plus 8 bytes just in case */
332             outSize = inSize + XMLSEC_OPENSSL_KW_AES_MAGIC_BLOCK_SIZE + 
333                                XMLSEC_OPENSSL_AES_BLOCK_SIZE;
334         } else {
335             outSize = inSize + XMLSEC_OPENSSL_AES_BLOCK_SIZE;
336         }
337
338         ret = xmlSecBufferSetMaxSize(out, outSize);
339         if(ret < 0) {
340             xmlSecError(XMLSEC_ERRORS_HERE, 
341                         xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
342                         "xmlSecBufferSetMaxSize",
343                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
344                         "outSize=%d", outSize);
345             return(-1);
346         }
347
348         if(transform->operation == xmlSecTransformOperationEncrypt) {
349             ret = xmlSecOpenSSLKWAesEncode(xmlSecBufferGetData(key), keySize,
350                                             xmlSecBufferGetData(in), inSize,
351                                             xmlSecBufferGetData(out), outSize);
352             if(ret < 0) {
353                 xmlSecError(XMLSEC_ERRORS_HERE, 
354                             xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
355                             "xmlSecOpenSSLKWAesEncode",
356                             XMLSEC_ERRORS_R_XMLSEC_FAILED,
357                             XMLSEC_ERRORS_NO_MESSAGE);
358                 return(-1);
359             }
360             outSize = ret;
361         } else {
362             ret = xmlSecOpenSSLKWAesDecode(xmlSecBufferGetData(key), keySize,
363                                             xmlSecBufferGetData(in), inSize,
364                                             xmlSecBufferGetData(out), outSize);
365             if(ret < 0) {
366                 xmlSecError(XMLSEC_ERRORS_HERE, 
367                             xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
368                             "xmlSecOpenSSLKWAesDecode",
369                             XMLSEC_ERRORS_R_XMLSEC_FAILED,
370                             XMLSEC_ERRORS_NO_MESSAGE);
371                 return(-1);
372             }
373             outSize = ret;
374         }
375
376         ret = xmlSecBufferSetSize(out, outSize);
377         if(ret < 0) {
378             xmlSecError(XMLSEC_ERRORS_HERE, 
379                         xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
380                         "xmlSecBufferSetSize", 
381                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
382                         "outSize=%d", outSize);
383             return(-1);
384         }
385         
386         ret = xmlSecBufferRemoveHead(in, inSize);
387         if(ret < 0) {
388             xmlSecError(XMLSEC_ERRORS_HERE, 
389                         xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
390                         "xmlSecBufferRemoveHead",
391                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
392                         "inSize%d", inSize);
393             return(-1);
394         }
395         
396         transform->status = xmlSecTransformStatusFinished;
397     } else if(transform->status == xmlSecTransformStatusFinished) {
398         /* the only way we can get here is if there is no input */
399         xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1);
400     } else {
401         xmlSecError(XMLSEC_ERRORS_HERE, 
402                     xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
403                     NULL,
404                     XMLSEC_ERRORS_R_INVALID_STATUS,
405                     "status=%d", transform->status);
406         return(-1);
407     }
408     return(0);
409 }
410
411 static xmlSecSize  
412 xmlSecOpenSSLKWAesGetKeySize(xmlSecTransformPtr transform) {
413     if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformKWAes128Id)) {
414         return(XMLSEC_OPENSSL_AES128_KEY_SIZE);
415     } else if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformKWAes192Id)) {
416         return(XMLSEC_OPENSSL_AES192_KEY_SIZE);
417     } else if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformKWAes256Id)) {
418         return(XMLSEC_OPENSSL_AES256_KEY_SIZE);
419     }
420     return(0);
421 }
422
423 /**
424  * http://www.w3.org/TR/xmlenc-core/#sec-Alg-SymmetricKeyWrap:
425  *
426  * Assume that the data to be wrapped consists of N 64-bit data blocks 
427  * denoted P(1), P(2), P(3) ... P(N). The result of wrapping will be N+1 
428  * 64-bit blocks denoted C(0), C(1), C(2), ... C(N). The key encrypting 
429  * key is represented by K. Assume integers i, j, and t and intermediate 
430  * 64-bit register A, 128-bit register B, and array of 64-bit quantities 
431  * R(1) through R(N).
432  *
433  * "|" represents concatentation so x|y, where x and y and 64-bit quantities, 
434  * is the 128-bit quantity with x in the most significant bits and y in the 
435  * least significant bits. AES(K)enc(x) is the operation of AES encrypting 
436  * the 128-bit quantity x under the key K. AES(K)dec(x) is the corresponding 
437  * decryption opteration. XOR(x,y) is the bitwise exclusive or of x and y. 
438  * MSB(x) and LSB(y) are the most significant 64 bits and least significant 
439  * 64 bits of x and y respectively.
440  *
441  * If N is 1, a single AES operation is performed for wrap or unwrap. 
442  * If N>1, then 6*N AES operations are performed for wrap or unwrap.
443  *
444  * The key wrap algorithm is as follows:
445  *
446  *   1. If N is 1:
447  *          * B=AES(K)enc(0xA6A6A6A6A6A6A6A6|P(1))
448  *          * C(0)=MSB(B)
449  *          * C(1)=LSB(B)
450  *      If N>1, perform the following steps:
451  *   2. Initialize variables:
452  *          * Set A to 0xA6A6A6A6A6A6A6A6
453  *          * Fori=1 to N,
454  *            R(i)=P(i)
455  *   3. Calculate intermediate values:
456  *          * Forj=0 to 5,
457  *                o For i=1 to N,
458  *                  t= i + j*N
459  *                  B=AES(K)enc(A|R(i))
460  *                  A=XOR(t,MSB(B))
461  *                  R(i)=LSB(B)
462  *   4. Output the results:
463  *          * Set C(0)=A
464  *          * For i=1 to N,
465  *            C(i)=R(i)
466  *
467  * The key unwrap algorithm is as follows:
468  *
469  *   1. If N is 1:
470  *          * B=AES(K)dec(C(0)|C(1))
471  *          * P(1)=LSB(B)
472  *          * If MSB(B) is 0xA6A6A6A6A6A6A6A6, return success. Otherwise, 
473  *            return an integrity check failure error.
474  *      If N>1, perform the following steps:
475  *   2. Initialize the variables:
476  *          * A=C(0)
477  *          * For i=1 to N,
478  *            R(i)=C(i)
479  *   3. Calculate intermediate values:
480  *          * For j=5 to 0,
481  *                o For i=N to 1,
482  *                  t= i + j*N
483  *                  B=AES(K)dec(XOR(t,A)|R(i))
484  *                  A=MSB(B)
485  *                  R(i)=LSB(B)
486  *   4. Output the results:
487  *          * For i=1 to N,
488  *            P(i)=R(i)
489  *          * If A is 0xA6A6A6A6A6A6A6A6, return success. Otherwise, return 
490  *            an integrity check failure error.
491  */
492 static const xmlSecByte xmlSecOpenSSLKWAesMagicBlock[XMLSEC_OPENSSL_KW_AES_MAGIC_BLOCK_SIZE] = { 
493     0xA6,  0xA6,  0xA6,  0xA6,  0xA6,  0xA6,  0xA6,  0xA6
494 };
495                                                 
496 static int      
497 xmlSecOpenSSLKWAesEncode(const xmlSecByte *key, xmlSecSize keySize,
498                          const xmlSecByte *in, xmlSecSize inSize,
499                          xmlSecByte *out, xmlSecSize outSize) {
500     AES_KEY aesKey;
501     xmlSecByte block[XMLSEC_OPENSSL_AES_BLOCK_SIZE];
502     xmlSecByte *p;
503     int N, i, j, t;
504     int ret;
505     
506     xmlSecAssert2(key != NULL, -1);
507     xmlSecAssert2(keySize > 0, -1);
508     xmlSecAssert2(in != NULL, -1);
509     xmlSecAssert2(inSize > 0, -1);
510     xmlSecAssert2(out != NULL, -1);
511     xmlSecAssert2(outSize >= inSize + 8, -1);
512
513     ret = AES_set_encrypt_key(key, 8 * keySize, &aesKey);
514     if(ret != 0) {
515         xmlSecError(XMLSEC_ERRORS_HERE, 
516                     NULL,
517                     "AES_set_encrypt_key",
518                     XMLSEC_ERRORS_R_CRYPTO_FAILED,
519                     XMLSEC_ERRORS_NO_MESSAGE);
520         return(-1);     
521     }
522
523     /* prepend magic block */
524     if(in != out) {
525         memcpy(out + XMLSEC_OPENSSL_KW_AES_MAGIC_BLOCK_SIZE, in, inSize);
526     } else {
527         memmove(out + XMLSEC_OPENSSL_KW_AES_MAGIC_BLOCK_SIZE, out, inSize);
528     }
529     memcpy(out, xmlSecOpenSSLKWAesMagicBlock, XMLSEC_OPENSSL_KW_AES_MAGIC_BLOCK_SIZE);
530     
531     N = (inSize / 8);
532     if(N == 1) {
533         AES_encrypt(out, out, &aesKey); 
534     } else {
535         for(j = 0; j <= 5; ++j) {
536             for(i = 1; i <= N; ++i) {
537                 t = i + (j * N);
538                 p = out + i * 8;
539
540                 memcpy(block, out, 8);
541                 memcpy(block + 8, p, 8);
542                 
543                 AES_encrypt(block, block, &aesKey);
544                 block[7] ^=  t;
545                 memcpy(out, block, 8);
546                 memcpy(p, block + 8, 8);
547             }
548         }
549     }
550     
551     return(inSize + 8);
552 }
553
554 static int      
555 xmlSecOpenSSLKWAesDecode(const xmlSecByte *key, xmlSecSize keySize,
556                          const xmlSecByte *in, xmlSecSize inSize,
557                          xmlSecByte *out, xmlSecSize outSize) {
558     AES_KEY aesKey;
559     xmlSecByte block[XMLSEC_OPENSSL_AES_BLOCK_SIZE];
560     xmlSecByte *p;
561     int N, i, j, t;
562     int ret;
563
564     xmlSecAssert2(key != NULL, -1);
565     xmlSecAssert2(keySize > 0, -1);
566     xmlSecAssert2(in != NULL, -1);
567     xmlSecAssert2(inSize > 0, -1);
568     xmlSecAssert2(out != NULL, -1);
569     xmlSecAssert2(outSize >= inSize, -1);
570     
571     ret = AES_set_decrypt_key(key, 8 * keySize, &aesKey);
572     if(ret != 0) {
573         xmlSecError(XMLSEC_ERRORS_HERE, 
574                     NULL,
575                     "AES_set_decrypt_key",
576                     XMLSEC_ERRORS_R_CRYPTO_FAILED,
577                     XMLSEC_ERRORS_NO_MESSAGE);
578         return(-1);     
579     }
580     
581     /* copy input */
582     if(in != out) {
583         memcpy(out, in, inSize);
584     }
585         
586     N = (inSize / 8) - 1;
587     if(N == 1) {
588         AES_decrypt(out, out, &aesKey);
589     } else {
590         for(j = 5; j >= 0; --j) {
591             for(i = N; i > 0; --i) {
592                 t = i + (j * N);
593                 p = out + i * 8;
594
595                 memcpy(block, out, 8);
596                 memcpy(block + 8, p, 8);
597                 block[7] ^= t;
598                 
599                 AES_decrypt(block, block, &aesKey);
600                 memcpy(out, block, 8);
601                 memcpy(p, block + 8, 8);
602             }
603         }
604     }
605     /* do not left data in memory */
606     memset(block, 0, sizeof(block));
607     
608     if(memcmp(xmlSecOpenSSLKWAesMagicBlock, out, XMLSEC_OPENSSL_KW_AES_MAGIC_BLOCK_SIZE) != 0) {
609         xmlSecError(XMLSEC_ERRORS_HERE, 
610                     NULL,
611                     NULL,
612                     XMLSEC_ERRORS_R_INVALID_DATA,
613                     "bad magic block");
614         return(-1);     
615     }
616         
617     memmove(out, out + XMLSEC_OPENSSL_KW_AES_MAGIC_BLOCK_SIZE, inSize - XMLSEC_OPENSSL_KW_AES_MAGIC_BLOCK_SIZE);
618     return(inSize - XMLSEC_OPENSSL_KW_AES_MAGIC_BLOCK_SIZE);
619 }
620
621 #endif /* XMLSEC_OPENSSL_096 */
622 #endif /* XMLSEC_NO_AES */