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