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  * OpenSSLCryptoBase64 := Base virtual class to define a base64 encoder/decoder
24  *
25  * Author(s): Berin Lautenbach
26  *
27  * $ID$
28  *
29  * $LOG$
30  *
31  */
32 
33 #include <xsec/framework/XSECDefs.hpp>
34 #if defined (XSEC_HAVE_OPENSSL)
35 
36 #include <xsec/enc/OpenSSL/OpenSSLCryptoBase64.hpp>
37 #include <xsec/enc/XSECCryptoException.hpp>
38 #include <xsec/enc/XSCrypt/XSCryptCryptoBase64.hpp>
39 #include <xsec/framework/XSECError.hpp>
40 
41 #include <xercesc/util/Janitor.hpp>
42 
43 #include <openssl/err.h>
44 
45 XERCES_CPP_NAMESPACE_USE
46 
47 // --------------------------------------------------------------------------------
48 //           Construction/Destruction
49 // --------------------------------------------------------------------------------
50 
51 #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)
OpenSSLCryptoBase64()52 OpenSSLCryptoBase64::OpenSSLCryptoBase64() : mp_ectx(&m_ectx_store), mp_dctx(&m_dctx_store) { }
~OpenSSLCryptoBase64()53 OpenSSLCryptoBase64::~OpenSSLCryptoBase64() { }
54 #else
55 OpenSSLCryptoBase64::OpenSSLCryptoBase64() : mp_ectx(EVP_ENCODE_CTX_new()), mp_dctx(EVP_ENCODE_CTX_new()) {
56     if (!mp_ectx || !mp_dctx)
57         throw XSECCryptoException(XSECCryptoException::ECError, "OpenSSL:CrypoBase64 - cannot allocate contexts");
58 };
59 OpenSSLCryptoBase64::~OpenSSLCryptoBase64() {
60     EVP_ENCODE_CTX_free(mp_ectx);
61     EVP_ENCODE_CTX_free(mp_dctx);
62 }
63 
64 #endif
65 // --------------------------------------------------------------------------------
66 //           Decoding
67 // --------------------------------------------------------------------------------
68 
decodeInit(void)69 void OpenSSLCryptoBase64::decodeInit(void) {
70 
71 	EVP_DecodeInit(mp_dctx);
72 
73 }
74 
decode(const unsigned char * inData,unsigned int inLength,unsigned char * outData,unsigned int outLength)75 unsigned int OpenSSLCryptoBase64::decode(const unsigned char * inData,
76 						 	    unsigned int inLength,
77 								unsigned char * outData,
78 								unsigned int outLength) {
79 
80 	int rc;
81 	int outLen;
82 
83 	if (outLength < inLength) {
84 
85 		throw XSECCryptoException(XSECCryptoException::MemoryError,
86 			"OpenSSL:Base64 - Output buffer not big enough for Base64 decode");
87 
88 	}
89 
90 	rc = EVP_DecodeUpdate(mp_dctx,
91 						  outData,
92 						  &outLen,
93 						  (unsigned char *) inData,
94 						  inLength);
95 
96 	if (rc < 0) {
97 
98 		throw XSECCryptoException(XSECCryptoException::Base64Error,
99 			"OpenSSL:Base64 - Error during Base64 Decode");
100 	}
101 
102 	if (outLen > (int) outLength) {
103 
104 		throw XSECCryptoException(XSECCryptoException::MemoryError,
105 			"OpenSSL:Base64 - Output buffer not big enough for Base64 decode and overflowed");
106 
107 	}
108 
109 	return outLen;
110 
111 }
112 
decodeFinish(unsigned char * outData,unsigned int outLength)113 unsigned int OpenSSLCryptoBase64::decodeFinish(unsigned char * outData,
114 							 	      unsigned int outLength) {
115 
116 	int outLen;
117 	outLen = outLength;
118 
119 	EVP_DecodeFinal(mp_dctx, outData, &outLen);
120 
121 	return outLen;
122 
123 }
124 
125 // --------------------------------------------------------------------------------
126 //           Encoding
127 // --------------------------------------------------------------------------------
128 
encodeInit(void)129 void OpenSSLCryptoBase64::encodeInit(void) {
130 
131 	EVP_EncodeInit(mp_ectx);
132 
133 }
134 
135 
encode(const unsigned char * inData,unsigned int inLength,unsigned char * outData,unsigned int outLength)136 unsigned int OpenSSLCryptoBase64::encode(const unsigned char * inData,
137 						 	    unsigned int inLength,
138 								unsigned char * outData,
139 								unsigned int outLength) {
140 
141 	int outLen;
142 
143 	if (outLength + 24 < inLength) {
144 
145 		throw XSECCryptoException(XSECCryptoException::MemoryError,
146 			"OpenSSL:Base64 - Output buffer not big enough for Base64 encode");
147 
148 	}
149 
150 	EVP_EncodeUpdate( mp_ectx,
151 					  outData,
152 					 &outLen,
153 					  (unsigned char *) inData,
154 					  inLength);
155 
156 	if (outLen > (int) outLength) {
157 
158 		throw XSECCryptoException(XSECCryptoException::MemoryError,
159 			"OpenSSL:Base64 - Output buffer not big enough for Base64 encode and overflowed");
160 
161 	}
162 
163 	return outLen;
164 
165 }
166 
encodeFinish(unsigned char * outData,unsigned int outLength)167 unsigned int OpenSSLCryptoBase64::encodeFinish(unsigned char * outData,
168 							 	      unsigned int outLength) {
169 
170 	int outLen;
171 	outLen = outLength;
172 
173 	EVP_EncodeFinal(mp_ectx, outData, &outLen);
174 
175 	return outLen;
176 
177 }
178 
179 // --------------------------------------------------------------------------------
180 //           Utility functions
181 // --------------------------------------------------------------------------------
182 
b642BN(char * b64in,unsigned int len)183 BIGNUM * OpenSSLCryptoBase64::b642BN(char * b64in, unsigned int len) {
184 
185 	if (len > 1024)
186 		return NULL;
187 
188 	int bufLen;
189 	unsigned char buf[1024];
190 /*
191 	EVP_ENCODE_CTX m_dctx;
192 	EVP_DecodeInit(&m_dctx);
193 	int rc = EVP_DecodeUpdate(&m_dctx,
194 						  buf,
195 						  &bufLen,
196 						  (unsigned char *) b64in,
197 						  len);
198 
199 	if (rc < 0) {
200 
201 		throw XSECCryptoException(XSECCryptoException::Base64Error,
202 			"OpenSSL:Base64 - Error during Base64 Decode of BIGNUMS");
203 	}
204 
205 	int finalLen;
206 	EVP_DecodeFinal(&m_dctx, &buf[bufLen], &finalLen);
207 
208 	bufLen += finalLen;
209 */
210 	XSCryptCryptoBase64 *b64;
211 	XSECnew(b64, XSCryptCryptoBase64);
212 	Janitor<XSCryptCryptoBase64> j_b64(b64);
213 
214 	b64->decodeInit();
215 	bufLen = b64->decode((unsigned char *) b64in, len, buf, len);
216 	bufLen += b64->decodeFinish(&buf[bufLen], len-bufLen);
217 
218 	// Now translate to a bignum
219 	return BN_bin2bn(buf, bufLen, NULL);
220 
221 }
222 
223 #endif /* XSEC_HAVE_OPENSSL */
224