1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 /*
21  * XSEC
22  *
23  * TXFMCipher := Class that performs encryption and decryption transforms
24  *
25  * $Id: TXFMCipher.cpp 1817135 2017-12-04 22:24:05Z scantor $
26  *
27  */
28 
29 // XSEC
30 
31 #include <xsec/framework/XSECDefs.hpp>
32 #include <xsec/transformers/TXFMCipher.hpp>
33 #include <xsec/utils/XSECPlatformUtils.hpp>
34 #include <xsec/framework/XSECException.hpp>
35 
36 XERCES_CPP_NAMESPACE_USE
37 
TXFMCipher(DOMDocument * doc,const XSECCryptoKey * key,bool encrypt,XSECCryptoSymmetricKey::SymmetricKeyMode mode,unsigned int taglen)38 TXFMCipher::TXFMCipher(DOMDocument *doc,
39 					   const XSECCryptoKey * key,
40 					   bool encrypt,
41                        XSECCryptoSymmetricKey::SymmetricKeyMode mode,
42                        unsigned int taglen) :
43 TXFMBase(doc),
44 m_doEncrypt(encrypt),
45 m_taglen(taglen),
46 mp_cipher(NULL),
47 m_remaining(0) {
48 
49     if (key && key->getKeyType() == XSECCryptoKey::KEY_SYMMETRIC)
50 	    mp_cipher = key->clone();
51 
52 	if (!mp_cipher) {
53 		throw XSECException(XSECException::CryptoProviderError,
54 				"Error cloning key, or not a symmetric key");
55 	}
56 
57 	m_complete = false;
58 
59 	try {
60 		if (m_doEncrypt)
61 			((XSECCryptoSymmetricKey *) (mp_cipher))->encryptInit((mode != XSECCryptoSymmetricKey::MODE_GCM), mode);
62 		else
63 			((XSECCryptoSymmetricKey *) (mp_cipher))->decryptInit((mode != XSECCryptoSymmetricKey::MODE_GCM), mode);
64 	}
65 	catch (...) {
66 		delete mp_cipher;
67 		mp_cipher = NULL;
68 		throw;
69 	}
70 
71 };
72 
~TXFMCipher()73 TXFMCipher::~TXFMCipher() {
74 
75 		delete mp_cipher;
76 
77 };
78 
79 	// Methods to set the inputs
80 
setInput(TXFMBase * newInput)81 void TXFMCipher::setInput(TXFMBase *newInput) {
82 
83 	input = newInput;
84 
85 	// Set up for comments
86 	keepComments = input->getCommentsStatus();
87 
88 }
89 
90 	// Methods to get tranform output type and input requirement
91 
getInputType(void) const92 TXFMBase::ioType TXFMCipher::getInputType(void) const {
93 
94 	return TXFMBase::BYTE_STREAM;
95 
96 }
getOutputType(void) const97 TXFMBase::ioType TXFMCipher::getOutputType(void) const {
98 
99 	return TXFMBase::BYTE_STREAM;
100 
101 }
102 
103 
getNodeType(void) const104 TXFMBase::nodeType TXFMCipher::getNodeType(void) const {
105 
106 	return TXFMBase::DOM_NODE_NONE;
107 
108 }
109 
110 // Methods to get output data
111 
readBytes(XMLByte * const toFill,unsigned int maxToFill)112 unsigned int TXFMCipher::readBytes(XMLByte * const toFill, unsigned int maxToFill) {
113 
114 	unsigned int ret, fill, leftToFill;
115 
116 	ret = 0;					// How much have we copied?
117 	leftToFill = maxToFill;		// Still have to copy in entire thing
118 
119 	while (ret != maxToFill && (m_complete == false || m_remaining > 0)) {
120 
121 		if (m_remaining != 0) {
122 
123 			// Copy anything remaining in the buffer to the output
124 
125 			fill = (leftToFill > m_remaining ? m_remaining : leftToFill);
126 			memcpy(&toFill[ret], m_outputBuffer, fill);
127 
128 			if (fill < m_remaining)
129 				memmove(m_outputBuffer, m_outputBuffer + fill, (m_remaining - fill));
130 
131 			m_remaining -= fill;
132 			leftToFill -= fill;
133 			ret += fill;
134 		}
135 
136 		// Now do some crypting
137 
138 		if (m_complete == false && m_remaining == 0) {
139 
140 			unsigned int sz = input->readBytes(m_inputBuffer, 2048);
141 
142 			XSECCryptoSymmetricKey * symCipher =
143 				(XSECCryptoSymmetricKey*) mp_cipher;
144 			if (m_doEncrypt) {
145 
146 				if (sz == 0) {
147 					m_complete = true;
148 					m_remaining = symCipher->encryptFinish(m_outputBuffer, 3072, m_taglen);
149 				}
150 				else
151 					m_remaining = symCipher->encrypt(m_inputBuffer, m_outputBuffer, sz, 3072);
152 			}
153 			else {
154 
155 				if (sz == 0) {
156 					m_complete = true;
157 					m_remaining = symCipher->decryptFinish(m_outputBuffer, 3072);
158 				}
159 				else
160 					m_remaining = symCipher->decrypt(m_inputBuffer, m_outputBuffer, sz, 3072);
161 			}
162 		}
163 
164 	}
165 
166 	return ret;
167 
168 }
169