1 /**
2  * Licensed to the University Corporation for Advanced Internet
3  * Development, Inc. (UCAID) under one or more contributor license
4  * agreements. See the NOTICE file distributed with this work for
5  * additional information regarding copyright ownership.
6  *
7  * UCAID licenses this file to you under the Apache License,
8  * Version 2.0 (the "License"); you may not use this file except
9  * in compliance with the License. You may obtain a copy of the
10  * License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the License is distributed on an
16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
17  * either express or implied. See the License for the specific
18  * language governing permissions and limitations under the License.
19  */
20 
21 #include "XMLObjectBaseTestCase.h"
22 
23 #include <xmltooling/exceptions.h>
24 #include <xmltooling/security/DataSealer.h>
25 
26 #include <fstream>
27 #include <xercesc/util/Base64.hpp>
28 #include <xsec/utils/XSECPlatformUtils.hpp>
29 
30 class DataSealerTest : public CxxTest::TestSuite {
31 public:
testStaticDataSealer()32     void testStaticDataSealer() {
33 #ifdef XSEC_OPENSSL_HAVE_GCM
34         unsigned char keybuf[32];
35         TS_ASSERT_EQUALS(sizeof(keybuf), XSECPlatformUtils::g_cryptoProvider->getRandom(keybuf, sizeof(keybuf)));
36 
37         XMLSize_t x;
38         XMLByte* encoded = Base64::encode(keybuf, sizeof(keybuf), &x);
39         TS_ASSERT_LESS_THAN(0, x);
40         auto_ptr_XMLCh widekey((char*)encoded);
41         XMLString::release((char**)&encoded);
42 
43         DOMDocument* doc = XMLToolingConfig::getConfig().getParser().newDocument();
44         Janitor<DOMDocument> jdoc(doc);
45 
46         static const XMLCh _key[] = UNICODE_LITERAL_3(k,e,y);
47         DOMElement* root = doc->createElementNS(nullptr, _key);
48         root->setAttributeNS(nullptr, _key, widekey.get());
49         doc->appendChild(root);
50 
51         auto_ptr<DataSealerKeyStrategy> keyStrategy(
52             XMLToolingConfig::getConfig().DataSealerKeyStrategyManager.newPlugin(
53                 STATIC_DATA_SEALER_KEY_STRATEGY, doc->getDocumentElement(), false
54                 )
55             );
56 
57 		keyStrategy->lock();
58         pair<string,const XSECCryptoSymmetricKey*> key = keyStrategy->getDefaultKey();
59         TS_ASSERT_EQUALS("static", key.first);
60         TSM_ASSERT_EQUALS("Wrong key type", key.second->getSymmetricKeyType(), XSECCryptoSymmetricKey::KEY_AES_256);
61 		keyStrategy->unlock();
62 
63         scoped_ptr<DataSealer> sealer(new DataSealer(keyStrategy.get()));
64 		keyStrategy.release();
65 
66         string data = "this is a test";
67 
68         string wrapped = sealer->wrap(data.c_str(), time(nullptr) + 500);
69         string unwrapped = sealer->unwrap(wrapped.c_str());
70 
71         TSM_ASSERT_EQUALS("DataSealer output did not match.", data, unwrapped);
72 
73         wrapped = sealer->wrap(data.c_str(), time(nullptr) - 500);
74         TSM_ASSERT_THROWS("DataSealer did not throw on expired data.", sealer->unwrap(wrapped.c_str()), IOException);
75 
76 		wrapped = sealer->wrap(data.c_str(), time(nullptr) - 500);
77 		wrapped.insert(0, "invalid");
78 		TSM_ASSERT_THROWS("DataSealer did not throw on wrong key label.", sealer->unwrap(wrapped.c_str()), IOException);
79 #endif
80     }
81 
testVersionedDataSealer()82 	void testVersionedDataSealer() {
83 #ifdef XSEC_OPENSSL_HAVE_GCM
84 		DOMDocument* doc = XMLToolingConfig::getConfig().getParser().newDocument();
85 		Janitor<DOMDocument> jdoc(doc);
86 
87 		static const XMLCh _path[] = UNICODE_LITERAL_4(p, a, t, h);
88 		DOMElement* root = doc->createElementNS(nullptr, _path);
89         string sealerpath = data_path + "sealer.keys";
90 		auto_ptr_XMLCh widepath(sealerpath.c_str());
91 		root->setAttributeNS(nullptr, _path, widepath.get());
92 		doc->appendChild(root);
93 
94 		auto_ptr<DataSealerKeyStrategy> keyStrategy(
95 			XMLToolingConfig::getConfig().DataSealerKeyStrategyManager.newPlugin(
96 				VERSIONED_DATA_SEALER_KEY_STRATEGY, doc->getDocumentElement(), false
97 			)
98 		);
99 
100 		keyStrategy->lock();
101 
102 		pair<string, const XSECCryptoSymmetricKey*> key = keyStrategy->getDefaultKey();
103 		TS_ASSERT_EQUALS("4", key.first);
104 		TSM_ASSERT_EQUALS("Wrong key type", key.second->getSymmetricKeyType(), XSECCryptoSymmetricKey::KEY_AES_128);
105 
106 		key.second = keyStrategy->getKey("1");
107 		TS_ASSERT(key.second != nullptr);
108 		TSM_ASSERT_EQUALS("Wrong key type", key.second->getSymmetricKeyType(), XSECCryptoSymmetricKey::KEY_AES_128);
109 
110 		keyStrategy->unlock();
111 
112 		scoped_ptr<DataSealer> sealer(new DataSealer(keyStrategy.get()));
113 		keyStrategy.release();
114 
115 		string data = "this is a test";
116 
117 		string wrapped = sealer->wrap(data.c_str(), time(nullptr) + 500);
118 		string unwrapped = sealer->unwrap(wrapped.c_str());
119 
120 		TSM_ASSERT_EQUALS("DataSealer output did not match.", data, unwrapped);
121 
122 		wrapped = sealer->wrap(data.c_str(), time(nullptr) - 500);
123 		TSM_ASSERT_THROWS("DataSealer did not throw on expired data.", sealer->unwrap(wrapped.c_str()), IOException);
124 
125 		wrapped = sealer->wrap(data.c_str(), time(nullptr) - 500);
126 		wrapped.insert(0, "invalid");
127 		TSM_ASSERT_THROWS("DataSealer did not throw on wrong key label.", sealer->unwrap(wrapped.c_str()), IOException);
128 #endif
129 	}
130 };
131