summaryrefslogtreecommitdiff
path: root/src/kw_aes_des.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kw_aes_des.c')
-rw-r--r--src/kw_aes_des.c493
1 files changed, 0 insertions, 493 deletions
diff --git a/src/kw_aes_des.c b/src/kw_aes_des.c
deleted file mode 100644
index 022e720a..00000000
--- a/src/kw_aes_des.c
+++ /dev/null
@@ -1,493 +0,0 @@
-/**
- * XML Security Library (http://www.aleksey.com/xmlsec).
- *
- * Implementation of AES/DES Key Transport algorithm
- *
- * This is free software; see Copyright file in the source
- * distribution for preciese wording.
- *
- * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
- */
-#include "globals.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <libxml/tree.h>
-
-#include <xmlsec/xmlsec.h>
-#include <xmlsec/errors.h>
-
-#include "kw_aes_des.h"
-
-#ifndef XMLSEC_NO_DES
-
-static int xmlSecKWDes3BufferReverse (xmlSecByte *buf,
- xmlSecSize size);
-
-/********************************************************************
- *
- * CMS Triple DES Key Wrap
- *
- * http://www.w3.org/TR/xmlenc-core/#sec-Alg-SymmetricKeyWrap
- *
- * The following algorithm wraps (encrypts) a key (the wrapped key, WK)
- * under a TRIPLEDES key-encryption-key (KEK) as specified in [CMS-Algorithms]:
- *
- * 1. Represent the key being wrapped as an octet sequence. If it is a
- * TRIPLEDES key, this is 24 octets (192 bits) with odd parity bit as
- * the bottom bit of each octet.
- * 2. Compute the CMS key checksum (section 5.6.1) call this CKS.
- * 3. Let WKCKS = WK || CKS, where || is concatenation.
- * 4. Generate 8 random octets [RANDOM] and call this IV.
- * 5. Encrypt WKCKS in CBC mode using KEK as the key and IV as the
- * initialization vector. Call the results TEMP1.
- * 6. Left TEMP2 = IV || TEMP1.
- * 7. Reverse the order of the octets in TEMP2 and call the result TEMP3.
- * 8. Encrypt TEMP3 in CBC mode using the KEK and an initialization vector
- * of 0x4adda22c79e82105. The resulting cipher text is the desired result.
- * It is 40 octets long if a 168 bit key is being wrapped.
- *
- * The following algorithm unwraps (decrypts) a key as specified in
- * [CMS-Algorithms]:
- *
- * 1. Check if the length of the cipher text is reasonable given the key type.
- * It must be 40 bytes for a 168 bit key and either 32, 40, or 48 bytes for
- * a 128, 192, or 256 bit key. If the length is not supported or inconsistent
- * with the algorithm for which the key is intended, return error.
- * 2. Decrypt the cipher text with TRIPLEDES in CBC mode using the KEK and
- * an initialization vector (IV) of 0x4adda22c79e82105. Call the output TEMP3.
- * 3. Reverse the order of the octets in TEMP3 and call the result TEMP2.
- * 4. Decompose TEMP2 into IV, the first 8 octets, and TEMP1, the remaining
- * octets.
- * 5. Decrypt TEMP1 using TRIPLEDES in CBC mode using the KEK and the IV found
- * in the previous step. Call the result WKCKS.
- * 6. Decompose WKCKS. CKS is the last 8 octets and WK, the wrapped key, are
- * those octets before the CKS.
- * 7. Calculate a CMS key checksum (section 5.6.1) over the WK and compare
- * with the CKS extracted in the above step. If they are not equal, return
- * error.
- * 8. WK is the wrapped key, now extracted for use in data decryption.
- *
- ********************************************************************/
-static xmlSecByte xmlSecKWDes3Iv[XMLSEC_KW_DES3_IV_LENGTH] = {
- 0x4a, 0xdd, 0xa2, 0x2c, 0x79, 0xe8, 0x21, 0x05
-};
-
-int
-xmlSecKWDes3Encode(xmlSecKWDes3Id kwDes3Id, void *context,
- const xmlSecByte *in, xmlSecSize inSize,
- xmlSecByte *out, xmlSecSize outSize) {
- xmlSecByte sha1[XMLSEC_KW_DES3_SHA_DIGEST_LENGTH];
- xmlSecByte iv[XMLSEC_KW_DES3_IV_LENGTH];
- xmlSecSize s;
- int ret;
-
- xmlSecAssert2(xmlSecKWDes3CheckId(kwDes3Id), -1);
- xmlSecAssert2(context != NULL, -1);
- xmlSecAssert2(in != NULL, -1);
- xmlSecAssert2(inSize > 0, -1);
- xmlSecAssert2(out != NULL, -1);
- xmlSecAssert2(outSize >= inSize + XMLSEC_KW_DES3_BLOCK_LENGTH + XMLSEC_KW_DES3_IV_LENGTH, -1);
-
- /* step 2: calculate sha1 and CMS */
- ret = kwDes3Id->sha1(context, in, inSize, sha1, sizeof(sha1));
- if((ret < 0) || (ret != sizeof(sha1))) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "kwDes3Id->sha1",
- XMLSEC_ERRORS_R_XMLSEC_FAILED,
- "ret=%d", ret);
- return(-1);
- }
-
- /* step 3: construct WKCKS as WK || CKS */
- memcpy(out, in, inSize);
- memcpy(out + inSize, sha1, XMLSEC_KW_DES3_BLOCK_LENGTH);
-
- /* step 4: generate random iv */
- ret = kwDes3Id->generateRandom(context, iv, sizeof(iv));
- if((ret < 0) || (ret != sizeof(iv))) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "kwDes3Id->generateRandom",
- XMLSEC_ERRORS_R_XMLSEC_FAILED,
- "ret=%d", ret);
- return(-1);
- }
-
- /* step 5: first encryption, result is TEMP1 */
- ret = kwDes3Id->encrypt(context,
- iv, sizeof(iv),
- out, inSize + XMLSEC_KW_DES3_BLOCK_LENGTH,
- out, outSize);
- if((ret < 0) || ((xmlSecSize)ret != inSize + XMLSEC_KW_DES3_BLOCK_LENGTH)) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "kwDes3Id->encrypt",
- XMLSEC_ERRORS_R_XMLSEC_FAILED,
- "ret=%d", ret);
- return(-1);
- }
-
- /* step 6: construct TEMP2=IV || TEMP1 */
- memmove(out + XMLSEC_KW_DES3_IV_LENGTH, out, inSize + XMLSEC_KW_DES3_BLOCK_LENGTH);
- memcpy(out, iv, XMLSEC_KW_DES3_IV_LENGTH);
- s = inSize + XMLSEC_KW_DES3_BLOCK_LENGTH + XMLSEC_KW_DES3_IV_LENGTH;
-
- /* step 7: reverse octets order, result is TEMP3 */
- ret = xmlSecKWDes3BufferReverse(out, s);
- if(ret < 0) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "xmlSecKWDes3BufferReverse",
- XMLSEC_ERRORS_R_XMLSEC_FAILED,
- "ret=%d", ret);
- return(-1);
- }
-
- /* step 8: second encryption with static IV */
- ret = kwDes3Id->encrypt(context,
- xmlSecKWDes3Iv, sizeof(xmlSecKWDes3Iv),
- out, s,
- out, outSize);
- if((ret < 0) || ((xmlSecSize)ret != s)) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "kwDes3Id->encrypt",
- XMLSEC_ERRORS_R_XMLSEC_FAILED,
- "ret=%d", ret);
- return(-1);
- }
-
- s = ret;
- return(s);
-}
-
-int
-xmlSecKWDes3Decode(xmlSecKWDes3Id kwDes3Id, void *context,
- const xmlSecByte *in, xmlSecSize inSize,
- xmlSecByte *out, xmlSecSize outSize)
-{
- xmlSecByte sha1[XMLSEC_KW_DES3_SHA_DIGEST_LENGTH];
- xmlSecSize s;
- int ret;
-
- xmlSecAssert2(xmlSecKWDes3CheckId(kwDes3Id), -1);
- xmlSecAssert2(context != NULL, -1);
- xmlSecAssert2(in != NULL, -1);
- xmlSecAssert2(inSize > 0, -1);
- xmlSecAssert2(out != NULL, -1);
- xmlSecAssert2(outSize >= inSize, -1);
-
-
- /* step 2: first decryption with static IV, result is TEMP3 */
- ret = kwDes3Id->decrypt(context,
- xmlSecKWDes3Iv, sizeof(xmlSecKWDes3Iv),
- in, inSize,
- out, outSize);
- if((ret < 0) || (ret < XMLSEC_KW_DES3_IV_LENGTH)) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "kwDes3Id->decrypt",
- XMLSEC_ERRORS_R_XMLSEC_FAILED,
- "ret=%d", ret);
- return(-1);
- }
- s = ret;
-
- /* step 3: reverse octets order in TEMP3, result is TEMP2 */
- ret = xmlSecKWDes3BufferReverse(out, s);
- if(ret < 0) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "xmlSecKWDes3BufferReverse",
- XMLSEC_ERRORS_R_XMLSEC_FAILED,
- "ret=%d", ret);
- return(-1);
- }
-
- /* steps 4 and 5: get IV and decrypt second time, result is WKCKS */
- ret = kwDes3Id->decrypt(context,
- out, XMLSEC_KW_DES3_IV_LENGTH,
- out + XMLSEC_KW_DES3_IV_LENGTH, s - XMLSEC_KW_DES3_IV_LENGTH,
- out, outSize);
- if((ret < 0) || (ret < XMLSEC_KW_DES3_BLOCK_LENGTH)) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "kwDes3Id->decrypt",
- XMLSEC_ERRORS_R_XMLSEC_FAILED,
- "ret=%d", ret);
- return(-1);
- }
- s = ret - XMLSEC_KW_DES3_BLOCK_LENGTH;
-
- /* steps 6 and 7: calculate SHA1 and validate it */
- ret = kwDes3Id->sha1(context,
- out, s,
- sha1, sizeof(sha1));
- if((ret < 0) || (ret != sizeof(sha1))) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "kwDes3Id->sha1",
- XMLSEC_ERRORS_R_XMLSEC_FAILED,
- "ret=%d", ret);
- return(-1);
- }
-
- /* check sha1 */
- xmlSecAssert2(XMLSEC_KW_DES3_BLOCK_LENGTH <= sizeof(sha1), -1);
- if(memcmp(sha1, out + s, XMLSEC_KW_DES3_BLOCK_LENGTH) != 0) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- NULL,
- XMLSEC_ERRORS_R_INVALID_DATA,
- "SHA1 does not match");
- return(-1);
- }
-
- /* done */
- return(s);
-}
-
-static int
-xmlSecKWDes3BufferReverse(xmlSecByte *buf, xmlSecSize size)
-{
- xmlSecByte * p;
- xmlSecByte ch;
-
- xmlSecAssert2(buf != NULL, -1);
- xmlSecAssert2(size > 0, -1);
-
- for(p = buf + size - 1; p >= buf; ++buf, --p) {
- ch = (*p);
- (*p) = (*buf);
- (*buf) = ch;
- }
- return (0);
-}
-
-#endif /* XMLSEC_NO_DES */
-
-
-
-#ifndef XMLSEC_NO_AES
-/********************************************************************
- *
- * KT AES
- *
- * 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.
- ********************************************************************/
-static const xmlSecByte xmlSecKWAesMagicBlock[XMLSEC_KW_AES_MAGIC_BLOCK_SIZE] = {
- 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6
-};
-
-int
-xmlSecKWAesEncode(xmlSecKWAesId kwAesId, void *context,
- const xmlSecByte *in, xmlSecSize inSize,
- xmlSecByte *out, xmlSecSize outSize) {
- xmlSecByte block[XMLSEC_KW_AES_BLOCK_SIZE];
- xmlSecByte *p;
- int N, i, j, t;
- int ret;
-
- xmlSecAssert2(kwAesId != NULL, -1);
- xmlSecAssert2(kwAesId->encrypt != NULL, -1);
- xmlSecAssert2(kwAesId->decrypt != NULL, -1);
- xmlSecAssert2(context != NULL, -1);
- xmlSecAssert2(in != NULL, -1);
- xmlSecAssert2(inSize > 0, -1);
- xmlSecAssert2(out != NULL, -1);
- xmlSecAssert2(outSize >= inSize + XMLSEC_KW_AES_MAGIC_BLOCK_SIZE, -1);
-
- /* prepend magic block */
- if(in != out) {
- memcpy(out + XMLSEC_KW_AES_MAGIC_BLOCK_SIZE, in, inSize);
- } else {
- memmove(out + XMLSEC_KW_AES_MAGIC_BLOCK_SIZE, out, inSize);
- }
- memcpy(out, xmlSecKWAesMagicBlock, XMLSEC_KW_AES_MAGIC_BLOCK_SIZE);
-
- N = (inSize / 8);
- if(N == 1) {
- ret = kwAesId->encrypt(out, inSize + XMLSEC_KW_AES_MAGIC_BLOCK_SIZE, out, outSize, context);
- if(ret < 0) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "kwAesId->encrypt",
- XMLSEC_ERRORS_R_XMLSEC_FAILED,
- XMLSEC_ERRORS_NO_MESSAGE);
- return(-1);
- }
- } 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);
-
- ret = kwAesId->encrypt(block, sizeof(block), block, sizeof(block), context);
- if(ret < 0) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "kwAesId->encrypt",
- XMLSEC_ERRORS_R_XMLSEC_FAILED,
- XMLSEC_ERRORS_NO_MESSAGE);
- return(-1);
- }
- block[7] ^= t;
- memcpy(out, block, 8);
- memcpy(p, block + 8, 8);
- }
- }
- }
-
- return(inSize + 8);
-}
-
-int
-xmlSecKWAesDecode(xmlSecKWAesId kwAesId, void *context,
- const xmlSecByte *in, xmlSecSize inSize,
- xmlSecByte *out, xmlSecSize outSize) {
- xmlSecByte block[XMLSEC_KW_AES_BLOCK_SIZE];
- xmlSecByte *p;
- int N, i, j, t;
- int ret;
-
- xmlSecAssert2(kwAesId != NULL, -1);
- xmlSecAssert2(kwAesId->encrypt != NULL, -1);
- xmlSecAssert2(kwAesId->decrypt != NULL, -1);
- xmlSecAssert2(context != NULL, -1);
- xmlSecAssert2(in != NULL, -1);
- xmlSecAssert2(inSize > 0, -1);
- xmlSecAssert2(out != NULL, -1);
- xmlSecAssert2(outSize >= inSize, -1);
-
- /* copy input */
- if(in != out) {
- memcpy(out, in, inSize);
- }
-
- N = (inSize / 8) - 1;
- if(N == 1) {
- ret = kwAesId->decrypt(out, inSize, out, outSize, context);
- if(ret < 0) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "kwAesId->decrypt",
- XMLSEC_ERRORS_R_XMLSEC_FAILED,
- XMLSEC_ERRORS_NO_MESSAGE);
- return(-1);
- }
- } 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;
-
- ret = kwAesId->decrypt(block, sizeof(block), block, sizeof(block), context);
- if(ret < 0) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- "kwAesId->decrypt",
- XMLSEC_ERRORS_R_XMLSEC_FAILED,
- XMLSEC_ERRORS_NO_MESSAGE);
- return(-1);
- }
- memcpy(out, block, 8);
- memcpy(p, block + 8, 8);
- }
- }
- }
- /* do not left data in memory */
- memset(block, 0, sizeof(block));
-
- /* check the output */
- if(memcmp(xmlSecKWAesMagicBlock, out, XMLSEC_KW_AES_MAGIC_BLOCK_SIZE) != 0) {
- xmlSecError(XMLSEC_ERRORS_HERE,
- NULL,
- NULL,
- XMLSEC_ERRORS_R_INVALID_DATA,
- "bad magic block");
- return(-1);
- }
-
- /* get rid of magic block */
- memmove(out, out + XMLSEC_KW_AES_MAGIC_BLOCK_SIZE, inSize - XMLSEC_KW_AES_MAGIC_BLOCK_SIZE);
- return(inSize - XMLSEC_KW_AES_MAGIC_BLOCK_SIZE);
-}
-
-#endif /* XMLSEC_NO_AES */
-